本文讲解了重点面试问题CPU利用率高如何排查和解决。
点击上方“后端开发技术”,选择“设为星标” ,优质资源及时送达
CPU利用率高怎么办?如何排查和解决
这是一个常见的面试问题,也是线上常遇到的问题之一。遇到线上服务器异常告警,我们的首要目标不是定位问题,而是尽快恢复服务可用,消除影响。
往往这种时候不能一次性定位并解决问题,如果服务不可用我们要优先让服务可用,如果有数据异常我们要优先修复数据,也可能对此有应急方案,优先让服务恢复正常是重中之重。然后我们可以尽量去保留现场信息,比如内存dump、mysql log、gc log等,事后再去定位、解决问题和复盘。
通常会收到监控系统告警,相关服务器负载异常,cpu使用率过高
原因:可能是业务代码死循环、GC频繁、线程阻塞等
为了在测试环境模拟这种情况,这里以一个简单的死循环为例子,具体操作如下:
1.可以直接在服务器创建文件
touch Test.java
2.然后编辑Test.java
文件
vi Test.java
输入如下代码,然后wq
保存。
- public class Test {
- public static void main(String[] args) {
- Thread thread = new Thread(() -> {
- int a = 3;
- while (true) {
- if (a == 3) {
- a = a / 2;
- } else {
- a = 3;
- }
- }
- });
- thread.start();
- }
- }
3.命令行编译生成 Test.class
文件。
javac Test.java
4.命令行执行测试文件。
java Test
1.执行top 命令查看占用cpu最多的Java进程。
top
2.根据pid找到对应cpu占用最多的Java线程。
top -Hp 4861
3.将10进制线程id转换为16进制。
- [root@node1 ~]# printf '%x\n' 4861
- 12fd
4.通过jstack
命令找到对应问题现场堆栈信息。
- root@node1 ~]# jstack 4851|grep 12fd -C 10
- 2022-06-07 19:01:25
- Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.281-b09 mixed mode):
-
- "Attach Listener" #10 daemon prio=9 os_prio=0 tid=0x00007fe7c8001000 nid=0x14fa waiting on condition [0x0000000000000000]
- java.lang.Thread.State: RUNNABLE
-
- "DestroyJavaVM" #9 prio=5 os_prio=0 tid=0x00007fe7f0009800 nid=0x149a waiting on condition [0x0000000000000000]
- java.lang.Thread.State: RUNNABLE
-
- "Thread-0" #8 prio=5 os_prio=0 tid=0x00007fe7f00f6000 nid=0x12fd runnable [0x00007fe7f411a000]
- java.lang.Thread.State: RUNNABLE
- at Test.lambda$main$0(Test.java:7)
- at Test$$Lambda$1/471910020.run(Unknown Source)
- at java.lang.Thread.run(Thread.java:748)
-
- "Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007fe7f00b6000 nid=0x14a1 runnable [0x0000000000000000]
- java.lang.Thread.State: RUNNABLE
-
- "C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007fe7f00b3800 nid=0x14a0 waiting on condition [0x0000000000000000]
- java.lang.Thread.State: RUNNABLE
可以看到,问题线程处于runnable状态,可以对应定位到问题代码Test.java:7
,发现死循环。
对于CPU占用率飙高的场景,刚才列举的测试代码只是一种情况,还有如下可能。
1.业务线程出现大量阻塞,比如synchronized锁,可以检索状态为BLOCKED
的线程找到堆栈信息,然后分析。
2.网络IO或者磁盘IO阻塞导致的,排查方法和上面一样。
3.GC线程频繁导致,线程的标识为GC task thread
,对于这种情况可能是年轻代设置不合理、大对象分配过多,old区存活对象过多,具体问题具体分析。
如果对你有帮助,欢迎点赞、评论或分享,感谢阅读!