前言
“滴滴滴...” 手机突然收到阿里云云监控的报警短信:“您的ECS实例 CPU使用率已超过 90%”。
此时,你的服务可能响应缓慢,甚至直接502。面对这种情况,很多新手的反应是直接重启服务器。虽然重启能暂时解决问题,但找不到根因,问题迟早会卷土重来。
今天,我将分享一套**“教科书级”**的CPU飙高排查思路,只需几行命令,就能精准定位到是哪一行代码搞崩了服务器。
第一步:全局定位——找到耗资源的进程 (PID)
首先,我们需要知道是哪个程序(进程)占用了CPU。
- 在终端输入
top命令。 - 进入界面后,按下大写
P键,系统会按照 CPU使用率 对进程进行降序排列。
Bash
top - 14:28:32 up 10 days, 3:14, 2 users, load average: 2.10, 1.05, 0.56 Tasks: 102 total, 1 running, 101 sleeping, 0 stopped, 0 zombie %Cpu(s): 98.5 us, 1.2 sy, 0.0 ni, 0.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 12345 root 20 0 2.5g 500m 10m S 99.0 20.5 10:15.20 java
分析:如上图所示,PID为 12345 的 java 进程CPU占用率高达 99.0%,它就是我们要找的目标。
第二步:深度挖掘——找到耗资源的线程 (TID)
一个进程往往包含多个线程,我们需要知道具体是哪个线程在“作恶”。
使用命令 top -Hp <PID>,其中 <PID> 替换为上一步找到的进程ID。
Bash
# 查看进程 12345 下的所有线程 top -Hp 12345
进入界面后,同样按下 P 键排序:
Bash
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 12368 root 20 0 2.5g 500m 10m R 95.5 0.0 05:10.20 java 12369 root 20 0 2.5g 500m 10m S 1.2 0.0 00:05.10 java
分析:我们发现 PID(在线程视图中其实是 Thread ID)为 12368 的线程占用了绝大部分CPU。
第三步:进制转换——准备定位代码
Linux中的线程ID是十进制的(如 12368),而在Java堆栈日志中,线程ID通常是以十六进制(Hex)显示的。我们需要进行一次转换。
可以使用 printf 命令:
Bash
# 将 12368 转换为十六进制 printf "%x\n" 12368
输出:3050
记下这个十六进制数字:0x3050。
第四步:真相大白——定位具体代码行数
现在我们有了进程ID(12345)和十六进制的线程ID(0x3050),就可以使用 Java 自带的 jstack 工具来导出堆栈信息,并抓取“案发现场”。
Bash
# 打印堆栈信息,并使用 grep 查找 0x3050,显示匹配行的后 20 行 jstack 12345 | grep "0x3050" -A 20
输出示例:
"Thread-5" #25 prio=5 os_prio=0 tid=0x00007f8... nid=0x3050 runnable [0x00007f8...] java.lang.Thread.State: RUNNABLE at com.example.demo.controller.TestController.loop(TestController.java:28) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ...
终极分析:仔细看输出日志的 at com.example.demo.controller.TestController.loop(TestController.java:28)。 真相只有一个:在 TestController.java 文件的第 28 行。
通常这里可能存在:
- 死循环: 代码逻辑错误导致
while(true)且没有退出条件。 - 频繁GC: 如果看到是
GC task thread占用高,说明内存泄露导致了频繁的 Full GC。 - 复杂计算: 大量的数学运算或加密解密操作。
总结
以后遇到 CPU 100% 的情况,不要慌,按照这个套路走:
top→ 找 进程ID (PID)top -Hp PID→ 找 线程ID (TID)printf "%x\n" TID→ 转 十六进制 (Hex)jstack PID | grep Hex -A 20→ 找 问题代码
掌握这个排查链路,你就是团队里那个能“秒级定位问题”的专家!