Linux 服务器 CPU 性能排查方法
当服务器整体响应变慢、负载(load average)异常升高、QPS/吞吐下降、请求延迟抖动或用户反馈“卡顿”时,CPU 瓶颈 是最常见嫌疑之一。但“CPU 高”并不等于“CPU 就是瓶颈”——它可能是计算密集、锁竞争、上下文切换爆炸、调度延迟、虚拟化偷窃周期(steal)等不同子类的表现。
本文给出从快速判断 → 分类定位 → 深度剖析的完整、可操作排查路径,适用于物理机、虚拟机、容器宿主机场景(2026 年主流内核 6.6–6.12+)。
第一步:快速确认是否真的是 CPU 瓶颈(1–3 分钟)
跑以下命令组合,建立初步画像:
- 负载与运行队列uptime 或 cat /proc/loadavg → load average(1/5/15 min)持续 > 核数 × 1.5–2.5,且 runq-sz(运行队列长度) 高 → 有 CPU 相关等待
- top / htop 概览(最重要第一屏)
- 按 1 查看每个核使用率
- 按 P 排序进程(Shift+P)
- 看 %Cpu(s) 行: us(用户态)+ sy(内核态)持续 > 80–90% id(idle) < 10–20% wa/iowait 低(<5–10%) hi(硬件中断)、si(软中断)、st(steal)是否异常高
- mpstat 细看多核(sysstat 包) mpstat -P ALL 1 5 → 看每个核的 %usr + %sys 是否均衡;是否有单核 100% 而其他闲置(热核问题)
- vmstat 看队列与上下文vmstat 1 5 → r(运行队列)持续 > 核数 × 1.5–2 → cs(上下文切换)每秒上万甚至数十万 → 可能线程/锁爆炸
一句话判断标准:
- us + sy 高 + idle 低 + runq-sz 高 → 真 CPU 计算瓶颈
- us + sy 不高 + load 高 + cs 高 → 假高负载(锁、调度、大量阻塞等待)
- st(steal)>5–10% 持续 → 虚拟化宿主机超卖或 noisy neighbor
第二步:区分 CPU 瓶颈的 5 大子类型(3–10 分钟)
| 子类型 | 典型特征(top/mpstat/vmstat) | 关键指标阈值参考 | 常见罪魁祸首 | 下一秒确认命令 |
|---|---|---|---|---|
| 用户态计算密集 | us 很高(>70–90%),sy 低,单/少量进程吃核 | us >70%,单个进程 %CPU 接近 100% | 死循环、正则匹配、加密/压缩、数值计算 | top 按 P → pidstat -u 1 5 | sort -k8 -nr |
| 内核态密集 | sy 高(>30–60%),us 不高 | sy >30–50%,softirq 高 | 网络栈(高 PPS)、iptables 规则爆炸、ksoftirqd | mpstat 1 5、sar -q 1 5、cat /proc/softirqs |
| 上下文切换爆炸 | cs 每秒上万–数十万,load 高但 us/sy 不极高 | cs > 10k–50k/s | 线程过多、锁竞争、频繁 futex/epoll_wait | vmstat 1、pidstat -w 1 5(看 cswch/s) |
| 运行队列饱和 | runq-sz 持续远超核数,r 列高,idle 低 | runq-sz > 核数×2–3 | 大量可运行线程抢核 | vmstat 1、mpstat -P ALL 1 |
| 虚拟化偷窃周期 | st(steal)>5–20%,宿主机超卖或 noisy neighbor | steal >5–10% 持续 | 云厂商超售、其他 VM 抢占 | mpstat -P ALL 1、virt-top(如果有权限) |
第三步:锁定具体进程 / 线程 / 热点(5–30 分钟)
根据第二步结论,选择对应工具:
A. 用户态 CPU 消耗型
- pidstat -u 1 5 | sort -k 8 -nr | head -15 → Top CPU 进程/线程
- top → 按 P 排序 → 按 t 切换线程视图(看多线程程序哪个线程吃 CPU)
- perf top(实时热点)或 perf record -F 99 -p PID -g — sleep 30 → 生成火焰图(需 flamegraph 工具)
B. 内核态 / 软中断型
- cat /proc/softirqs → 看 NET_RX / NET_TX / SCHED 是否爆炸
- sar -I SUM 1 5 或 mpstat -I ALL 1 5 → 中断统计
- perf record -e irq:* -a — sleep 10 → 中断火焰图
C. 高上下文切换 / 锁竞争型
- pidstat -w 1 5 → 看 cswch/s(自愿切换)和 nvcswch/s(非自愿)
- strace -c -p PID 或 strace -f -p PID -c → 看是否卡在 futex
- perf record -e syscalls:sys_enter_futex … → futex 等待分析
- bpftrace 一行脚本:追踪 mutex、spinlock 持有时间
D. Java / Node.js / Python 等解释型语言
- perf 需要特殊处理(–all-user 或 jitdump)
- async-profiler(Java)或 perf-map-agent
- Node –prof + v8 火焰图
第四步:验证 + 根因闭环 + 临时缓解
- 临时缓解(争取时间):
- taskset -c 0-15 PID → 绑核减少争抢
- renice -n -5 -p PID 或 chrt 调整优先级
- systemctl restart 服务 或 kill -STOP / kill -CONT 暂停嫌疑进程观察
- 确认根因:
- perf 火焰图 + 代码/配置对比
- journalctl -k | grep -i sched / cpu
- dmesg | grep -i “rcu|softlockup”
- 长期方案:
- 升级内核(EEVDF 调度器 6.6+ 改善延迟)
- 调 sysctl(sched_migration_cost、sched_autogroup_enabled)
- 拆分单线程瓶颈(多进程/多实例)
- 加核 / 换更高主频机型
完整排查口诀(Netflix 60s 精神延伸版):
“uptime 看 load → top/mpstat 看 us/sy/id/st → vmstat 看 r/cs → pidstat/perf 找热点 → 火焰图定函数 → 代码/配置/锁确认”
按这个顺序,90% 的 CPU 相关性能问题都能在 20–40 分钟内找到主要瓶颈,避免盲目加机器或重启。熟练后可直接用 perf/bpftrace 一键采集 30 秒样本生成火焰图,成为定位神器。