返回首页

Linux 服务器 CPU 飙高排查 — 完整方法论 + 应急响应实战

📅 创建于 2026-05-11 🔄 更新于 2026-05-19 📝 1144 字

Linux 服务器 CPU 飙高排查:一套实战定位思路

CPU 问题排查的核心链路:先分层,再深入;先分态,再取证;先保现场,再做动作。 整机 → 进程 → 线程 → 调用栈,顺着四层往下走,判断不会跑偏。


一、快速诊断三问

问题 命令 判断要点
整机还是单进程? mpstat -P ALL 1 3 / ps -eo pid,%cpu --sort=-%cpu 所有核都高→流量/全局中断;单核高→单线程热点
用户态还是系统态? top -b -n 1 | head -10 / mpstat -P ALL 1 5 %usr高→应用代码;%sys高→内核/中断/网络;%steal高→宿主机抢资源
哪个线程/栈在热? top -H -p <PID>perf top -p <PID> -g 固定占满单核→死循环/自旋锁;多线程高→并发放大


二、整机级判断(先别急着动)

# 一轮命令固定现场
date && hostname -f && uptime
w
top -b -n 1 | head -20
mpstat -P ALL 1 3
vmstat 1 5
sar -u 1 5
sar -q 1 5
free -h
df -h
dmesg -T | tail -50

关键指标解读:

指标 含义 异常阀值
%usr 用户态 CPU 高了先看应用进程/线程热点
%sys 系统态 CPU 高了先看网络/磁盘/中断/内核路径
%iowait IO 等待 ⚠️ 很多人误判成 CPU 问题,根因在 IO
%steal 虚拟化偷取 云主机关键指标,>5% 找云平台
run queue (r) 运行队列 持续 > CPU 核数 → 调度压力大
load average 负载均值 不等于 CPU 打满,需结合 IO 判断

三、用户态 vs 系统态

区分方向

CPU mode 排查方向 典型根因
%usr + %nice 应用进程 代码热点、死循环、JSON 编解码、正则、GC、压缩解压
%sys 内核路径 系统调用密集、网络包处理、软中断、连接风暴
%soft 软中断 网卡小包洪峰、iptables/conntrack 压力
%irq 硬中断 网卡队列、某些存储控制器异常
%steal 宿主机 不是你机器的问题,先找云平台

%sys 高 → 继续定位

cat /proc/softirqs
cat /proc/interrupts
sar -n DEV,EDEV 1 5
ethtool -S eth0 | egrep 'drop|miss|error|timeout'

%usr 高 → 进入进程/线程定位


四、进程级定位

# 找 CPU 高的进程
ps -eo pid,ppid,lstart,etime,pcpu,pmem,cmd --sort=-pcpu | head -20

# 看进程周期性 CPU 走势
pidstat -u -t -p <PID> 1 5

# 看进程打开的文件描述符
lsof -p <PID> | head -50

不同语言排查路径

语言 工具 命令
Java top + jstack top -H -p <PID>printf '0x%x\\n' <TID>jstack <PID> \| grep -A 20 <hex>
Go pprof curl -s http://127.0.0.1:6060/debug/pprof/profile?seconds=30 -o cpu.pprofgo tool pprof -top cpu.pprof
Python top + strace top -H -p <PID>strace -p <PID> -c(统计模式)

实战判断点

  • 新拉起的进程 CPU 高 → 新版本发布、配置变更、缓存未热
  • 运行几天后的进程 CPU 高 → 线程泄漏、连接泄漏、任务堆积、GC 退化
  • 只有某个工作线程高 → 优先抓线程栈,不要先抓完整堆 dump

五、线程级定位(最有价值的一步)

# 查看进程内线程 CPU
top -H -p <PID>
ps -Lp <PID> -o pid,tid,psr,pcpu,stat,comm --sort=-pcpu | head -20
pidstat -t -p <PID> 1 5

# perf 热点采样(比 strace 更适合 CPU 分析)
sudo perf top -p <PID> -g # 实时查看
sudo perf record -F 99 -p <PID> -g -- sleep 30 # 采样留存
sudo perf report --stdio | head -80 # 查看热点函数
现象 结论
某个线程固定占满 100% 单核 典型死循环、自旋锁、空轮询
多个线程同时高 并发打满、线程池放大、热点 key
CPU 高 + 上下文切换也高 锁竞争、频繁唤醒、线程数过多

六、系统态 CPU 高:中断/网络/磁盘

排查顺序:网卡收发 → 软中断分布 → 连接状态 → 磁盘队列 → 内核日志

sar -n DEV,EDEV,TCP,ETCP 1 5
ss -s
ss -ant state syn-recv
netstat -s | egrep -i 'listen|overflow|drop|retrans'
cat /proc/softirqs
cat /proc/net/softnet_stat
iostat -xz 1 5
pidstat -d 1 5
模式 根因 解决
NET_RX 飙高 小包洪峰、负载均衡不均、网卡队列/中断绑核不合理 启用 irqbalance、调多队列、绑核
ksoftirqd 软中断堆积 检查网卡中断分布
SYN-RECV 很多 连接风暴、半连接队列不足 调大 somaxconntcp_max_syn_backlog

七、云主机/容器特殊检查

# 宿主机抢占
mpstat -P ALL 1 5 # 看 %steal

# 容器 CPU 节流
grep . /sys/fs/cgroup/cpu.max 2>/dev/null || cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us
cat /sys/fs/cgroup/cpu.stat 2>/dev/null

# K8s 视角
kubectl top node
kubectl top pod -A --containers | head -30
kubectl describe node <name> | egrep -A3 'Allocated resources'

⚠️ 容器 CPU 100% 先换算: 500m 配额下 100% ≠ 整机 100%。nr_throttled 持续增长说明被节流。


八、案例复盘

案例 1:Java 线程死循环打满单核

现象: 订单服务发布后 RT 从 30ms → 800ms,单核 100%

排查: top -H -p 28461 → 线程 28513 占 99% → jstack 显示卡在规则引擎死循环

// 问题代码:死循环 + 正则匹配 3 万条规则
while (true) {
 for (String rule : rules) {
 if (rule.matches(".*VIP.*")) { ... }
 }
}

修复: 摘流 → 回滚 → 缓存预编译规则替代 matches → 加退出条件

效果: 单核 99% → 整机 31%,P99 1.2s → 85ms

案例 2:软中断堆积导致网关 %sys 70%

现象: API 网关高峰 %sys 70%,NET_RX 在 CPU0/1 严重倾斜

排查: cat /proc/softirqs 发现 NET_RX 不均 → ksoftirqd/0 持续占 CPU

修复: 启用 irqbalance + 调整 smp_affinity 使中断均衡分布

效果: %sys 72% → 28%,超时率 5.4% → 0.3%

九、应急响应 — 先止血再排查

CPU 飙到 100% 时,先保护现场再止血,优先恢复业务而非根因分析。

应急流程

  1. 固定现场top -b -n1 / mpstat / vmstat / dmesg -T | tail -50 留存
  2. 判断影响 — 单机还是集群?单进程还是全局?有无关联告警?
  3. 止血 — 根据场景选择以下措施
  4. 通知 — 同步值班群:影响范围 + 已采取措施 + 预计恢复时间
  5. 复盘 — 事后写 RCA(Root Cause Analysis)

止血手段

场景 止血操作 命令
单进程 CPU 打满 kill 或 restart kill -15 <PID> / systemctl restart <svc>
流量突增 限流/降级 Nginx limit_req / Sentinel 降级
代码 Bug(刚发布) 回滚 kubectl rollout undo
机器异常 摘流/切走流量 摘除 LB 后端
集群级 紧急扩容 kubectl scale --replicas=N

常见根因速查

根因 快速确认 特征
死循环 perf top -p <PID> 看热点函数 单核 100%,固定线程
GC 频繁 jstat -gc <PID> 1s %usr 高 + 内存波动
正则回溯 strace -p <PID> 大量重复调用 单线程高 + 响应慢
加密/压缩 perf top 看 crypto/zlib 函数 %usr 高 + 吞吐低
短连接风暴 ss -s 看 TIME-WAIT 数 %sys + %soft 高
挖矿病毒 ps 找到未知进程 + lsof -p <PID> 陌生进程名、持续 100%
容器限流 cat .../cpu.stat 看 nr_throttled stretch 高但 sys/user 不高

十、常驻监控与告警

关键指标

# 整机 CPU > 85% 持续 5 分钟
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85

# 软中断占比 > 25% 持续 3 分钟
avg by(instance) (rate(node_cpu_seconds_total{mode="softirq"}[5m])) * 100 > 25

# 容器节流持续增长
sum by(pod, namespace) (rate(container_cpu_cfs_throttled_periods_total[5m])) > 20

自动快照脚本

当 CPU 告警触发时,自动执行 /usr/local/bin/cpu_hotspot_snapshot.sh 保存现场(详见 raw 源文件)。


关联页面

页面 关联点
cpu-spike-3-commands CPU 飙高三命令速查(top → strace -c → /proc/PID/fd/,同伴快速参考)
server-performance-four-dimensions 服务器五维排查(CPU/内存/磁盘/网络/文件系统)
linux-load-average-guide Load Average 完全解读(iowait vs CPU 判断)
linux-server-load-case-study 负载过高排查案例实战(含 CPU 场景)
linux-disk-io-tuning 磁盘 IO 调优(%sys 高的 IO 路径排查)
linux-api-performance-tuning-case-study Linux 系统调优实战案例(CPU→JVM→网络全栈)
linux-load-high-cpu-low-troubleshooting Linux Load 高但 CPU 低的排查思路 — 从现象确认到根因定位的系统化诊断流程(含 vm
linux-perf-troubleshooting-handbook Linux 服务器性能排查实战手册 — 60 秒快速摸底/4 大瓶颈排查/3 个实战案例/监控阈值/
online-troubleshooting-checklist 四维排查速查清单(CPU/磁盘/内存/网络 + Java 工具 jstack/jmap/jstat/tcpdump)