服务器 CPU 飙高排查
问题
收到告警:某台服务器 CPU 使用率持续超过 90%,如何排查?
答案
排查流程
Step 1:查看整体指标
# 查看 CPU 使用率概览
top -bn1 | head -5
# %Cpu(s): 92.3 us, 3.1 sy, 0.0 ni, 3.5 id, 0.8 wa, 0.0 hi, 0.3 si
# 按 CPU 排序查看进程
top -bn1 -o %CPU | head -20
# 查看每个 CPU 核心的使用率(按 1 展开)
mpstat -P ALL 1 3
CPU 使用率类型
- us (user):用户态,应用代码消耗 → 代码/算法问题
- sy (system):内核态,系统调用多 → 频繁 IO / 锁竞争
- wa (iowait):等待 IO → 磁盘瓶颈
- si (softirq):软中断 → 大量网络包处理
Step 2:定位高 CPU 进程
# 找到占用 CPU 最高的进程
ps aux --sort=-%cpu | head -10
# 如果是 Java 进程,找到高 CPU 线程
# 1. 获取进程 PID(假设 PID=12345)
top -Hp 12345 # 按线程查看,找到高 CPU 的线程 TID
# 2. 转换 TID 为十六进制(假设 TID=12367)
printf "%x\n" 12367 # 输出: 304f
# 3. 用 jstack 导出线程栈
jstack 12345 | grep -A 20 "0x304f"
# 如果是 Go 进程
# 访问 pprof 接口
curl http://localhost:6060/debug/pprof/profile?seconds=30 > cpu.prof
go tool pprof cpu.prof
Step 3:使用 perf 分析热点函数
# 采样 30 秒,找到 CPU 热点函数
perf top -p 12345
# 录制并生成火焰图
perf record -p 12345 -g -- sleep 30
perf script > perf.data.txt
# 使用 FlameGraph 工具生成火焰图
git clone https://github.com/brendangregg/FlameGraph.git
./FlameGraph/stackcollapse-perf.pl perf.data.txt | \
./FlameGraph/flamegraph.pl > flamegraph.svg
常见原因及解决方案
| 原因 | 特征 | 解决方案 |
|---|---|---|
| 死循环 | 单核 100%,us 高 | 查代码逻辑 |
| 正则回溯 | us 高,单线程 CPU 满 | 优化正则或设超时 |
| GC 频繁 | Java sy 高,jstat 看 GC | 调整 JVM 参数 |
| 连接风暴 | sy 高,连接数暴涨 | 限流、连接池 |
| 加密/压缩 | us 高,openssl 函数热点 | 硬件加速卸载 |
| 日志打印过多 | wa + sy 高 | 降低日志级别 |
| 恶意请求 | si 高或 us 高 | WAF 拦截、限流 |
常见面试问题
Q1: Java 应用 CPU 飙高的完整排查思路?
答案:
# 1. top 找到 Java 进程 PID
top -c # 找到 CPU 最高的 java 进程,假设 PID=1234
# 2. top -Hp 找到高 CPU 线程
top -Hp 1234 # 假设最高的线程 TID=1256
# 3. TID 转十六进制
printf "%x\n" 1256 # 输出: 4e8
# 4. jstack 导出并搜索
jstack 1234 > /tmp/thread.dump
grep -A 30 "nid=0x4e8" /tmp/thread.dump
# 5. 分析线程栈
# 常见模式:
# - RUNNABLE + 业务代码 → 死循环或高计算
# - BLOCKED → 锁竞争
# - GC 线程占满 → 内存不足,频繁 GC(jstat -gc 1234 1000 确认)
Q2: iowait 高但磁盘 IO 不高,可能是什么原因?
答案:
iowait 表示 CPU 空闲且有 IO 请求等待。如果 iostat 显示磁盘 IO 不高,可能原因:
- NFS/网络文件系统:远程文件系统响应慢
- swap 活动:内存不足导致 swap IO(
vmstat 1查看 si/so) - 少量大 IO:单次 IO 很大,IOPS 低但延迟高(关注
await而非r/s)