跳到主要内容

服务器 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 不高,可能原因:

  1. NFS/网络文件系统:远程文件系统响应慢
  2. swap 活动:内存不足导致 swap IO(vmstat 1 查看 si/so)
  3. 少量大 IO:单次 IO 很大,IOPS 低但延迟高(关注 await 而非 r/s

相关链接