Linux 服务器 CPU 飙高排查实战:从 top 到火焰图
一、先看全局:top 的三行关键信息
登录服务器第一件事不是急着重启进程,而是花 30 秒看清全局。第一行 load average 的三个数值分别代表 1、5、15 分钟负载,经验判断标准是单核负载持续超过 0.7 就值得关注。第三行 %Cpu(s) 里的四个字段含义必须分清:
%Cpu(s): 85.3 us, 8.1 sy, 0.0 ni, 0.0 id, 6.2 wa, 0.1 hi, 0.3 si
us 高说明是用户态业务代码在消耗 CPU;sy 高意味着内核态繁忙,常见于海量系统调用或频繁上下文切换;wa 高则是 IO 等待,CPU 其实在“闲着等磁盘”,优化方向完全不同;si 高要怀疑软中断,典型场景是网卡流量打满。按大写 P 键以 CPU 占用排序,记下嫌疑进程的 PID。
二、线程级定位:pidstat
top 默认只展示进程维度,多线程程序需要下钻到线程。pidstat 加 -t 参数按 1 秒间隔输出线程级数据,能直接看到哪个 TID 在燃烧 CPU:
pidstat -t -p $(pidof java) 1 5
# 拿到热点 TID 后转 16 进制供 jstack 使用:
printf '%x\n' 12345
对 Java 服务,把热点 TID 转 16 进制后在 jstack 输出里搜索 nid=0x3039 即可锁定具体线程栈,这一步通常能直接定位到业务代码行。
三、判断阻塞还是计算:strace
如果进程 CPU 高但逻辑上看不出在忙什么,用 strace 统计系统调用分布,-c 汇总模式比逐行跟踪直观得多:
strace -c -f -p 12345
# 关注 calls 列异常多的调用与 errors 列:
strace -T -e trace=network -p 12345 2>&1 | head -50
若 errors 列出现大量 ENOENT 或 EAGAIN,多半是代码在疯狂重试;若 futex 调用占比极高,则是锁竞争,方向应转向并发逻辑审查而不是加机器。
四、终极手段:perf 火焰图
常规工具都解决不了时,perf 采样加火焰图能给出函数级答案:
perf record -F 99 -p 12345 -g -- sleep 30
perf script | stackcollapse-perf.pl | flamegraph.pl > cpu.svg
火焰图中横向越宽的函数占用 CPU 越多,热点路径一眼可见。采样频率选 99Hz 是刻意避开与其他周期性活动产生共振。
五、沉淀成决策树
整个排查可以固化成一条路径:top 看 us/sy/wa 定方向,pidstat 下钻线程,计算型问题走 perf 火焰图,阻塞型问题走 strace,Java 程序优先用 jstack 对热点 TID。多数 CPU 告警在前两步就能收敛,真正的功夫在于把每个工具的输出和“用户态、内核态、IO 等待”三种 CPU 消耗模型对应起来,避免南辕北辙。
- 点赞
- 收藏
- 关注作者
评论(0)