Linux CPU 飙高的 10 大根因与排查思路!
环境与版本矩阵
|
工具/命令 |
RHEL 7.x |
RHEL 8.x |
Ubuntu 18.04 |
用途 |
安装包 |
|---|---|---|---|---|---|
|
top |
原生 |
原生 |
原生 |
实时进程监控 |
- |
|
htop |
yum |
dnf |
apt |
增强 top |
htop |
|
perf |
yum install perf |
dnf |
apt |
CPU 火焰图 |
linux-tools |
|
sar |
sysstat |
sysstat |
sysstat |
系统历史统计 |
sysstat |
|
strace |
yum |
dnf |
apt |
系统调用追踪 |
strace |
|
mpstat |
sysstat |
sysstat |
sysstat |
单核 CPU 监控 |
sysstat |
|
iostat |
sysstat |
sysstat |
sysstat |
I/O 关联 CPU |
sysstat |
快速清单(Checklist)
- • [ ] 第1步:实时监控整体 CPU 使用率
- • [ ] 第2步:定位消耗 CPU 最高的单个进程。
- • [ ] 第3步:深入分析问题进程的线程与系统调用。
- • [ ] 第4步:收集历史性能数据排查波动规律。
- • [ ] 第5步:分析代码/系统调用热点(火焰图)。
- • [ ] 第6步:判断根因(业务逻辑、死循环、I/O 阻塞、内核 bug)。
- • [ ] 第7步:实施修复方案与回滚策略。
- • [ ] 第8步:建立长期监控告警。
实施步骤
Step 1:快速诊断整体 CPU 状态
查看系统平均负载:
代码语言:javascript
AI代码解释
# 方法 1:使用 uptime
uptime
# 方法 2:查看 /proc/loadavg
cat /proc/loadavg
预期输出:
代码语言:javascript
AI代码解释
10:45:32 up 10 days, 3:20, 2 users, load average: 2.45, 2.30, 2.15
参数解释:
- •
load average: 2.45, 2.30, 2.15:分别为 1 分钟、5 分钟、15 分钟平均负载。 - • 负载 = CPU 繁忙 + 等待队列。
- • 判断规则:负载 > CPU 核心数 说明系统饱和。
查看 CPU 核心数:
代码语言:javascript
AI代码解释
nproc
# 或
grep -c '^processor' /proc/cpuinfo
查看每个核心 CPU 使用率(实时):
代码语言:javascript
AI代码解释
# 方法 1:使用 mpstat(需 sysstat)
sudo mpstat -P ALL 1 5
# 方法 2:使用 top
top
mpstat 预期输出:
代码语言:javascript
AI代码解释
CPU %usr %nice %sys %iowait %irq %soft %guest %idle
0 45.2 0.0 8.5 2.1 0.0 0.1 0.0 44.1
1 78.9 0.0 15.3 2.1 0.0 0.1 0.0 3.6
2 12.3 0.0 5.6 1.2 0.0 0.0 0.0 80.9
关键字段解释:
- •
%usr:用户态 CPU(业务进程)。 - •
%sys:系统态 CPU(内核调用)。 - •
%iowait:等待 I/O 的 CPU(磁盘/网络 I/O)。 - •
%idle:空闲 CPU。
Step 2:定位高 CPU 消耗进程
使用 top 找高 CPU 进程:
代码语言:javascript
AI代码解释
top
交互命令:
- •
Shift + P:按 CPU 使用率排序(默认)。 - •
Shift + M:按内存使用率排序。 - •
d 1:刷新频率改为 1 秒。 - •
q:退出。
预期输出示例:
代码语言:javascript
AI代码解释
PID USER PR NI VIRT RES %CPU %MEM TIME+ COMMAND
5678 www 20 0 512m 256m 95.2 5.6 45:23 java -jar app.jar
1234 mysql 20 0 1.5g 800m 12.3 22.1 102:45 /usr/sbin/mysqld
使用 ps 查看特定进程 CPU:
代码语言:javascript
AI代码解释
# 查看所有进程按 CPU 排序(静态快照)
ps aux --sort=-%cpu | head -10
# 查看特定进程 CPU
ps -p 5678 -o pid,cmd,%cpu,%mem
# 查看进程所有线程的 CPU
ps -p 5678 -L -o pid,tid,cmd,%cpu
预期输出:
代码语言:javascript
AI代码解释
PID CMD %CPU %MEM
5678 java -jar app.jar 95.2 5.6
定位线程级热点(多线程应用):
代码语言:javascript
AI代码解释
# 查看进程的线程信息
ps -eLf | grep 5678
# 实时监控线程 CPU 使用
top -p 5678 -H
Step 3:深入分析问题进程的系统调用
使用 strace 追踪系统调用:
代码语言:javascript
AI代码解释
# 追踪特定进程的所有系统调用
sudo strace -p 5678 -e trace=all -c
# 统计系统调用耗时(找耗时操作)
sudo strace -p 5678 -c -S time
预期输出(strace -c):
代码语言:javascript
AI代码解释
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
45.20 2.451234 245 10000 0 futex
32.10 1.743210 174 10010 0 poll
15.30 0.831245 83 10020 0 read
5.40 0.293215 29 10030 0 write
参数说明:
- •
futex:线程间同步/互斥锁等待(高频表示锁竞争激烈)。 - •
poll/epoll:I/O 多路复用等待。 - • 高
%time的调用需进一步优化。
使用 perf 获取 CPU 火焰图(精确定位热点):
代码语言:javascript
AI代码解释
# 安装 perf
sudo yum install -y perf # RHEL/CentOS
# 或
sudo apt-get install -y linux-tools-generic # Ubuntu
# 采样特定进程 30 秒
sudo perf record -p 5678 -F 99 sleep
# 生成报告
sudo perf report
# 导出为火焰图格式(需自行处理数据)
sudo perf script > out.perf
perf report 交互命令:
- •
↓↑:上下导航。 - •
Enter:展开详情。 - •
q:退出。
Step 4:收集历史 CPU 数据排查规律
使用 sar 查看历史 CPU 数据:
代码语言:javascript
AI代码解释
# 需先启用 sysstat(编辑 /etc/cron.d/sysstat 或系统服务)
sudo yum install -y sysstat
# 查看今天的 CPU 使用历史(10 分钟一个采样点)
sar -u -f /var/log/sa/sa$(date +%d)
# 查看过去 7 天的每小时平均 CPU
sar -u -f /var/log/sa/sa01 -b
# 按 1 分钟间隔采集数据(实时)
sar -u 1 10
预期输出:
代码语言:javascript
AI代码解释
10:30:00 AM CPU %user %nice %system %iowait %steal %idle
10:31:00 AM all 45.23 0.00 8.45 2.34 0.00 43.98
10:32:00 AM all 48.12 0.01 9.21 1.87 0.00 40.79
识别 CPU 高峰规律:
代码语言:javascript
AI代码解释
# 查看过去 24 小时的 CPU 趋势
sar -u -f /var/log/sa/sa$(date +%d) | tail -20
Step 5:分析代码热点(火焰图)
生成 CPU 火焰图(Java 应用示例):
代码语言:javascript
AI代码解释
# Step 1:安装 flamegraph 工具
git clone https://github.com/brendangregg/FlameGraph.git
export PATH=$PATH:$(pwd)/FlameGraph
# Step 2:使用 perf 采样
sudo perf record -F 99 -p 5678 -g -- sleep
# Step 3:导出调用栈
sudo perf script > out.perf
# Step 4:生成火焰图
stackcollapse-perf.pl out.perf | flamegraph.pl > cpu_flame.svg
# Step 5:用浏览器查看 cpu_flame.svg
火焰图解读:
- • 横向宽度:函数调用次数(越宽表示消耗 CPU 时间越多)。
- • 纵向高度:调用栈深度。
- • 点击区域可进行交互(放大、重置)。
Step 6:CPU 飙高的 10 大根因与判断标准
|
根因 |
症状表现 |
诊断命令 |
判断标准 |
快速修复 |
|---|---|---|---|---|
|
1. 业务代码 CPU 密集 |
CPU 持续高位,%usr 高 |
perf report |
火焰图中业务函数占比 > 70% |
优化算法/加缓存 |
|
2. 死循环/无限递归 |
单进程 CPU 100%,无 I/O 等待 |
strace -p PID -c |
某个系统调用极高频 |
查代码、打日志 |
|
3. 锁竞争激烈 |
%sys 高,futex 系统调用多 |
strace -p PID -e futex |
futex 高频且耗时 |
减少临界区、细粒度锁 |
|
4. 频繁上下文切换 |
CPU 高但不满载、进程数多 |
vmstat 1 | watch -n 1 |
cs(上下文切换)> 50000/s |
限制线程数/使用 CPU 亲和性 |
|
5. 中断处理过多 |
%irq/%soft 高 |
cat /proc/interrupts |
网卡/存储中断高 |
调整网卡/磁盘驱动参数 |
|
6. I/O 密集(隐性 CPU) |
%iowait 高、等待 I/O 的进程多 |
iostat -x 1 |
wa > 20% |
优化 I/O 模式/换 SSD |
|
7. 内核内存回收 |
%sys 高、free 内存低 |
vmstat 1 | awk '{print $8}' |
kswapd 进程 CPU 高 |
增加内存/优化应用内存 |
|
8. 网络收包处理 |
%irq/%soft 高、网络流量大 |
sar -n DEV 1 10 |
Rxpck/s > 100k |
调整网卡中断配置/增加队列 |
|
9. 进程调度抖动 |
进程 CPU 波动大、缓存命中率低 |
perf stat -p PID -e cache-misses |
cache miss > 30% |
绑定 CPU/优化内存访问模式 |
|
10. 内核 bug/驱动问题 |
无明显业务高负载但 CPU 高 |
sudo dmesg | tail |
内核 Warning/Error 日志 |
升级内核/驱动版本 |
Step 7:实施修复方案
方案 A:进程级优化(不重启应用):
代码语言:javascript
AI代码解释
# 1. 限制进程 CPU 使用(cgroup)
cgcreate -g cpu:/limited_app
cgset -r cpu.cfs_quota_us=80000 /limited_app # 限制为 80% 一个 CPU
cgexec -g cpu:/limited_app /opt/app/start.sh
# 2. CPU 亲和性绑定(避免频繁迁移)
taskset -pc 0,1,2 5678 # 绑定进程 5678 到 CPU 0,1,2
# 3. 调整进程优先级
nice -n 10 /opt/app/start.sh # 降低优先级
# 或
renice -n 10 -p 5678
方案 B:系统级调优:
代码语言:javascript
AI代码解释
# 1. 禁用 CPU 频率缩放(固定最高频率以提升性能)
sudo vi /etc/default/grub
# 添加启动参数:intel_pstate=disable cpufreq=performance
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
sudo reboot
# 2. 调整进程调度器
echo deadline > /sys/block/sda/queue/scheduler # 磁盘 I/O 调度
echo nohz_full=2-3 >> /proc/cmdline # 使用内核参数
# 3. 关闭不必要的中断
sudo ethtool -C eth0 rx-usecs 500 # 调整网卡中断合并间隔
方案 C:应用代码优化(示例 - Python):
代码语言:javascript
AI代码解释
# 问题:频繁的全局 GIL 锁竞争
# 解决方案 1:使用多进程而非多线程
from multiprocessing import Process
defworker(data):
# CPU 密集操作
pass
if __name__ == '__main__':
processes = [Process(target=worker, args=(chunk,))
for chunk in data_chunks]
for p in processes:
p.start()
# 解决方案 2:使用 C 扩展或 NumPy(绕过 GIL)
import numpy as np
# NumPy 操作不受 GIL 限制
result = np.dot(matrix1, matrix2) # 并行计算
Step 8:建立监控告警
代码语言:javascript
AI代码解释
# prometheus.yml
scrape_configs:
-job_name:'node'
static_configs:
-targets: ['localhost:9100']
# alert_rules.yml
groups:
-name:cpu_alerts
rules:
-alert:CPUHigh
expr:(100-avgby(instance)(irate(node_cpu_seconds_total{mode="idle"}[5m]))*)>
for:5m
annotations:
summary:"High CPU on {{ $labels.instance }}"
-alert:LoadAverage
expr:node_load1>(countby(instance)(node_cpu_seconds_total{mode="idle"})*1.5)
for:5m
annotations:
summary:"High load average on {{ $labels.instance }}"
Grafana 仪表板指标:
- • CPU 使用率趋势(过去 24 小时)。
- • 单核 CPU 分布。
- • 进程 CPU TOP 10。
- • 负载均衡与调度延迟。
性能优化基准
CPU 优化目标:
- • 业务 CPU:降低 20-50%(通过算法/缓存优化)。
- • 系统 CPU:< 10%(正常运维开销)。
- • I/O 等待:< 5%(高效磁盘/网络配置)。
最佳实践
- 1. 分层排查:先看全局负载,再定位进程,最后深入代码。
- 2. 采样法排查:不要盲目优化,用 perf/火焰图找真正的热点。
- 3. 隔离问题进程:使用 cgroup 限制其他进程 CPU,确保主要服务可用。
- 4. 定期审计:每周查看 sar 历史数据,发现异常趋势。
- 5. 负载均衡:多进程/多线程充分利用多核,但注意锁竞争。
- 6. 版本控制:记录每次优化的内核/驱动/应用版本,便于回滚。
- 7. 测试验证:压测新优化方案,确保无副作用。
附录:常用命令速查
代码语言:javascript
AI代码解释
# 实时监控
top / htop / watch 'mpstat -P ALL 1 1'
# 历史数据
sar -u -f /var/log/sa/saXX
# 进程深度分析
ps aux / ps -eLf / top -H -p PID / ps -p PID -o tid,%cpu,cmd
# 系统调用追踪
strace -p PID -c -S time / sudo perf record -p PID -g
# 火焰图
sudo perf script | stackcollapse-perf.pl | flamegraph.pl
# 中断/负载
cat /proc/interrupts / vmstat 1 / uptime
# 调度统计
cat /proc/sched_debug / pidstat -w 1
总结:CPU 飙高排查需要分层思维——先看系统全局(负载、核心分布),再定位进程(top/ps),最后深入代码(perf/火焰图)。掌握 10 大根因的判断标准与快速诊断命令,就能在几分钟内找到病根。关键是搭建长期的 sar/Prometheus 监控,提前发现异常趋势,防患于未然。
更多推荐



所有评论(0)