2025年CPU使用率过高达到100%问题排查方法

CPU使用率过高达到100%问题排查方法最近在梳理自己曾经遇到过的一些问题 加深一下印象 温故而知新嘛 嘻嘻 公司商用环境曾经出现过某个服务 CPU 异常的高 导致监控服务频繁的给运维和开发人员发送异常告警通知 甚至影响了业务的处理性能 此时我们需要定位到异常的原因 并进行解决 通过这篇笔记

大家好,我是讯享网,很高兴认识大家。

​最近在梳理自己曾经遇到过的一些问题,加深一下印象,温故而知新嘛,嘻嘻~

1. 准备工作

为了能模拟出CPU占用过高的现象,这里我们需要准备一段代码,在代码中实现一段死循环的逻辑(众所周知,死循环是会导致CPU异常高的一种场景),相关代码如下:

public class CpuTooHighTest { 
    public static void main(String[] args) { 
    System.out.println("application start"); String str = "hello world!!!"; int i = 0; boolean check = true; while (check) { 
    //模拟业务逻辑,当符合某种条件时,将check设置为true,结束循环 //这里为了实现死循环,所以直接写死一种永远不可能为true的判断 1==2 if (1 == 2) { 
    check = false; } i++; } System.out.println("application end"); } } 

讯享网
讯享网java -cp cpu_too_high_test.jar CpuTooHighTest & 

java -cp 命令可以指定类运行所需要依赖的其他类的路径,一般是jar包、类库之类的;
上面的命令中 cpu_too_high_test.jar 是我打包出来的jar包名称,CpuTooHighTest 是代码中的类名,所以最终会执行CpuTooHighTest 这个类中的 main 函数。
到这里,已经启动了一个存在死循环的程序,并且启动之后可以看到CPU里面飙升到了100(我这里是运行在电脑的虚拟机中)

2. 定位出CPU异常的进程

使用TOP命令,查看当前服务器内所有进程的CPU使用情况

top - 16:04:39 up 3:24, 2 users, load average: 1.15, 1.26, 0.97 Tasks: 108 total, 1 running, 107 sleeping, 0 stopped, 0 zombie %Cpu(s): 99.7 us, 0.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem :  total,  free,  used,  buff/cache KiB Swap:  total,  free, 0 used.  avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 61001 root 20 0  22888 10492 S 99.3 1.2 18:28.63 java 1 root 20 0  6656 4164 S 0.0 0.4 0:01.20 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd 4 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H 5 root 20 0 0 0 0 S 0.0 0.0 0:00.80 kworker/u256:0 6 root 20 0 0 0 0 S 0.0 0.0 0:00.36 ksoftirqd/0 7 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0 8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh 9 root 20 0 0 0 0 S 0.0 0.0 0:00.77 rcu_sched 10 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 lru-add-drain 

很明显,可以发现 61001 这个 java 进程CPU使用率达到了 99.3%,罪魁祸首必然就是它了。

2.找出对应的线程

已经确定了61001这个进程,那我们接下来就可以使用命令找出对应的异常线程信息:

讯享网ps -mp { 
   pid} -o THREAD,tid,time | sort -rn 

将pid替换之后,执行结果如下:

[root@localhost apps]# ps -mp 61001 -o THREAD,tid,time | sort -rn USER %CPU PRI SCNT WCHAN USER SYSTEM TID TIME root 99.4 19 - - - - 61002 00:27:16 root 99.4 - - - - - - 00:27:16 root 0.0 19 - futex_ - - 61010 00:00:00 root 0.0 19 - futex_ - - 61009 00:00:00 root 0.0 19 - futex_ - - 61008 00:00:00 root 0.0 19 - futex_ - - 61007 00:00:00 root 0.0 19 - futex_ - - 61006 00:00:00 root 0.0 19 - futex_ - - 61005 00:00:00 root 0.0 19 - futex_ - - 61004 00:00:00 root 0.0 19 - futex_ - - 61003 00:00:00 root 0.0 19 - futex_ - - 61001 00:00:00 

可以发现,有一个线程CPU使用率很高,达到了99.4%,线程ID为61002,已经运行了 27分钟16秒


讯享网

3.TID转换成16进制

将TID转换成16进制的命令如下:

讯享网printf "%x\n" tid 

将tid替换成61002,执行结果如下:

[root@localhost apps]# printf "%x\n" 61002 ee4a 
4.使用jstack命令查看进程信息

使用jstack命令,可以查看到进程的信息,通过tid过滤可以更方便的进行查找

讯享网jstack -pid | grep 16进制tid 

替换pid、tid之后,执行命令:

[root@localhost apps]# jstack 61001 |grep ee4a "main" #1 prio=5 os_prio=0 tid=0x00007f0 nid=0xee4a runnable [0x00007f026b] 
讯享网jstack 61001 > 61001.txt 

查看打印出的信息如下:

...... 由于篇幅原因,省略前面部分内容 "Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f0 nid=0xee4c in Object.wait() [0x00007f02546fd000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000000e3806c00> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:502) at java.lang.ref.Reference.tryHandlePending(Reference.java:191) - locked <0x00000000e3806c00> (a java.lang.ref.Reference$Lock) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153) "main" #1 prio=5 os_prio=0 tid=0x00007f0 nid=0xee4a runnable [0x00007f026b] java.lang.Thread.State: RUNNABLE at CpuTooHighTest.main(CpuTooHighTest.java:15) "VM Thread" os_prio=0 tid=0x00007f026406e000 nid=0xee4b runnable "VM Periodic Task Thread" os_prio=0 tid=0x00007f02640bb000 nid=0xee52 waiting on condition JNI global references: 5 

通过上面tid得到的16进制,定位到关键内容

讯享网"main" #1 prio=5 os_prio=0 tid=0x00007f0 nid=0xee4a runnable [0x00007f026b] java.lang.Thread.State: RUNNABLE at CpuTooHighTest.main(CpuTooHighTest.java:15) 
5.代码排查

到这里,我们便可以定位到CPU被 CpuTooHighTest.java 中15行的代码给占用了,也就是说15行前后的代码存在问题,我们再回过头来看看最开始写的测试代码,为了方便查看,这里给每行代码都加上了行号

1 public class CpuTooHighTest { 
    2 3 public static void main(String[] args) { 
    4 System.out.println("application start"); 5 String str = "hello world!!!"; 6 7 int i = 0; 8 boolean check = true; 9 while (check) { 
    10 //模拟业务逻辑,当符合某种条件时,将check设置为true,结束循环 11 //这里为了实现死循环,所以直接写死一种永远不可能为true的判断 1==2 12 if (1 == 2) { 
    13 check = false; 14 } 15 i++; 16 } 17 18 System.out.println("application end"); 19 } 20 21 } 

其中,15行对应的代码为 i++,说明CPU一直在执行这一行代码,这与我们所写的死循环是一致的,到这里问题定位完成,我们只需要将对应的逻辑进行修复,避免出现死循环即可~

小讯
上一篇 2025-01-06 20:44
下一篇 2025-04-04 19:17

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/21450.html