1. 问题背景与CPU飙高的危害
CPU使用率突然飙升是Linux系统管理员最常遇到的性能问题之一。当服务器CPU使用率持续高于80%甚至达到100%时,系统响应会明显变慢,服务延迟增加,严重时可能导致服务不可用。这种情况我们通常称为"CPU飙高"或"CPU打满"。
CPU资源耗尽的影响是连锁式的:
- 首先表现为终端操作卡顿,命令响应延迟
- 随后系统进程调度延迟增加,关键服务无法及时获得CPU时间片
- 最终可能导致OOM Killer被触发,随机杀死进程释放内存
- 在容器化环境中,CPU限制可能导致容器被直接杀死重启
提示:当收到CPU告警时,建议立即保留现场并开始排查,避免直接重启服务或服务器,这样会丢失问题现场。
2. 快速定位CPU高负载进程
2.1 使用top命令初步定位
最快捷的方式是直接使用top命令:
top -c关键观察指标:
- %CPU列:显示每个进程的CPU占用百分比
- TIME+列:显示进程累计使用的CPU时间
- 负载平均值(load average):三个数值分别表示1分钟、5分钟、15分钟的平均负载
典型的高CPU进程会显示为:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1234 mysql 20 0 12.345g 2.345g 23456 R 99.6 5.8 10:23.45 /usr/sbin/mysqld2.2 更精细的进程分析工具
如果top显示的信息不够详细,可以使用:
ps -eo pid,user,%cpu,%mem,cmd --sort=-%cpu | head -n 10这个命令会按CPU使用率降序排列,显示前10个最耗CPU的进程。
对于Java应用,可以结合jstack分析:
# 先找到Java进程PID ps -ef | grep java # 然后获取线程堆栈 jstack -l <PID> > thread_dump.log3. 十大常见根因与排查方法
3.1 无限循环或死循环
特征:单个线程或进程持续占用100%的单个CPU核心
排查方法:
- 使用top -H -p 查看进程内的线程CPU占用
- 将高CPU线程ID转换为16进制:
printf "%x\n" <TID> - 在jstack或gdb输出的线程堆栈中搜索该16进制ID
典型案例:
- 递归调用没有终止条件
- while(true)循环内没有sleep或等待机制
- 第三方库中的bug导致逻辑卡死
3.2 锁竞争与死锁
特征:多个线程/进程的CPU使用率都很高,但系统吞吐量很低
排查工具:
- Java应用:jstack查看线程状态,关注BLOCKED状态的线程
- C/C++应用:gdb attach后执行thread apply all bt
- 系统级:perf锁分析
典型表现:
"Thread-1" #11 prio=5 os_prio=0 tid=0x00007f487c0b7000 nid=0x5e1 waiting for monitor entry [0x00007f487b5e9000] java.lang.Thread.State: BLOCKED (on object monitor held by Thread-0)3.3 频繁GC导致的CPU高
特征:周期性CPU高峰,GC日志中有大量Full GC记录
排查步骤:
- 检查JVM参数:
jinfo -flags <PID> - 获取GC统计:
jstat -gcutil <PID> 1000 10 - 分析GC日志(如果配置了-XX:+PrintGCDetails)
优化建议:
- 增加堆内存(-Xmx)
- 调整GC策略(如G1GC)
- 减少对象创建,避免内存泄漏
3.4 大量上下文切换
特征:CPU使用率高但us(user)不高,sy(system)很高
诊断命令:
vmstat 1 5关注cs列(上下文切换次数),正常应低于10000次/秒
常见原因:
- 进程/线程数过多
- 锁竞争激烈
- 不合理的进程调度策略
3.5 中断处理占用高CPU
特征:%si(软中断)或%hi(硬中断)指标异常高
诊断工具:
cat /proc/interrupts watch -n 1 'cat /proc/softirqs'常见场景:
- 网络包处理(如高PPS场景)
- 磁盘IO压力大
- 硬件设备异常
3.6 代码中的数学计算密集操作
特征:用户态CPU(%us)高,通常涉及科学计算、加密解密等
排查方法:
- perf top查看热点函数:
perf top -p <PID> - 使用strace跟踪系统调用:
strace -c -p <PID>
3.7 频繁的系统调用
特征:%sy(system)高,strace显示大量重复系统调用
典型案例:
- 循环中不必要的gettimeofday调用
- 过度日志记录(每次日志都调用write)
- 小文件频繁读写
3.8 配置不当的线程池
特征:线程数远多于CPU核心数,大量线程处于runnable状态
检查方法:
cat /proc/<PID>/status | grep Threads pstree -p <PID> | wc -l优化建议:
- 根据CPU核心数设置合理线程数
- 使用有界队列避免任务堆积
- 监控线程池活跃度
3.9 外部依赖响应慢
特征:等待IO时CPU看似空闲,但请求堆积导致后续CPU飙升
诊断工具:
iostat -x 1 # 查看await指标 netstat -antp | grep <PORT> # 查看连接状态3.10 内核模块或驱动问题
特征:内核态CPU(%sy)异常高,可能伴随内核日志报错
排查步骤:
- 检查内核日志:
dmesg -T | tail -50 - 使用perf分析内核调用:
perf record -ag -- sleep 10 perf report
4. 高级排查工具与技术
4.1 perf性能分析工具
perf是Linux内核自带的强大性能分析工具:
记录CPU热点:
perf record -F 99 -ag -- sleep 30 perf report火焰图生成:
perf script | stackcollapse-perf.pl | flamegraph.pl > flame.svg4.2 SystemTap动态追踪
对于复杂的内核级问题,可以使用SystemTap:
示例脚本(监控系统调用):
stap -e 'probe syscall.* { if (pid() == target()) printf("%s %d\n", name, pid()) }' -x <PID>4.3 ebpf工具集
现代Linux系统推荐使用ebpf工具:
CPU使用分析:
bpftrace -e 'profile:hz:99 { @[ustack] = count(); }'跟踪调度延迟:
funclatency -d 10 -u schedule5. 长期监控与预防措施
5.1 建立性能基线
记录正常时期的性能指标:
# CPU mpstat -P ALL 1 10 > cpu_baseline.log # 内存 vmstat 1 10 > mem_baseline.log # IO iostat -x 1 10 > io_baseline.log5.2 配置告警规则
使用Prometheus等工具监控关键指标:
groups: - name: CPU Alert rules: - alert: HighCPUUsage expr: 100 - (avg by(instance)(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80 for: 5m5.3 性能测试与调优
定期进行压力测试,提前发现问题:
# CPU压力测试 stress -c 8 -t 3006. 实战案例解析
6.1 MySQL查询导致CPU 100%
现象:mysqld进程持续占用高CPU
排查步骤:
- 查看当前运行查询:
SHOW FULL PROCESSLIST; - 分析慢查询日志:
mysqldumpslow -s t /var/log/mysql/mysql-slow.log - 使用EXPLAIN分析问题查询执行计划
解决方案:
- 添加缺失索引
- 重写复杂查询
- 优化JOIN操作
6.2 Java应用Full GC频繁
现象:周期性CPU高峰,应用响应变慢
排查步骤:
- 获取GC日志:
jstat -gcutil <PID> 1000 10 - 分析堆内存dump:
jmap -dump:live,format=b,file=heap.hprof <PID>
解决方案:
- 调整新生代与老年代比例
- 升级到G1GC收集器
- 修复内存泄漏问题
6.3 Nginx worker进程高CPU
现象:多个nginx worker进程占用高CPU
排查步骤:
- 检查活跃连接:
netstat -antp | grep nginx | wc -l - 分析访问日志:
awk '{print $7}' access.log | sort | uniq -c | sort -nr | head -20
解决方案:
- 优化高频率请求的location配置
- 启用缓存减少后端压力
- 调整worker_processes和worker_connections
7. 排查工具箱推荐
7.1 基础命令集
- CPU分析:top, htop, mpstat, pidstat
- 内存分析:free, vmstat, pmap
- IO分析:iostat, iotop, blktrace
- 网络分析:netstat, ss, tcpdump
7.2 高级分析工具
- perf:Linux内核性能分析工具
- strace:系统调用跟踪
- gdb:程序调试
- bpftrace:eBPF追踪工具
7.3 可视化工具
- nmon:终端可视化监控
- glances:综合监控工具
- Grafana:指标可视化
- 火焰图:性能热点可视化
8. 排查流程总结
- 确认现象:通过top/htop确认CPU使用率异常
- 定位进程:找出消耗CPU最高的进程
- 分析线程:对于多线程应用,定位具体线程
- 检查状态:分析进程/线程的当前状态(运行、阻塞、等待等)
- 获取堆栈:通过jstack/gdb等获取执行上下文
- 关联日志:结合系统日志和应用日志分析
- 复现验证:尝试复现问题并验证假设
- 实施修复:根据根因实施针对性的解决方案
经验分享:在实际排查中,经常遇到多个因素共同导致CPU高负载的情况。建议采用"排除法",先解决最明显的问题,然后观察系统行为变化。