CPU使用率100%的异常排查
点击勘误issues (opens new window),哪吒感谢大家的阅读

# CPU使用率100%的异常排查
在生产环境中,CPU使用率飙升至100%是一种常见的性能问题,可能导致系统响应缓慢甚至服务不可用。本文将详细介绍如何排查和解决CPU使用率100%的问题。
# 1. 问题表现
当CPU使用率达到100%时,系统通常会出现以下症状:
- 系统响应缓慢或无响应
- 应用程序执行速度变慢
- 请求处理时间增加
- 任务队列积压
- 服务超时或拒绝连接
# 2. 排查工具
# 2.1 Linux系统工具
top命令:实时显示系统中各个进程的资源占用情况
top
使用top命令后,可以按以下键进行排序:
- 按
P
键:按CPU使用率排序(默认) - 按
M
键:按内存使用率排序 - 按
T
键:按运行时间排序
htop命令:top的增强版,提供更友好的界面和更多功能
htop
ps命令:查看进程状态
# 查看CPU占用最高的前10个进程
ps aux | sort -k3nr | head -10
mpstat命令:查看多处理器统计信息
mpstat -P ALL 2 5 # 每2秒采样一次,共采样5次,显示所有CPU核心的统计信息
pidstat命令:监控进程的CPU使用情况
pidstat -u 2 5 # 每2秒采样一次,共采样5次
pidstat -p <PID> -u 2 5 # 监控特定进程
# 2.2 Java应用工具
jstack:生成Java线程转储
jstack <PID> > thread_dump.log
jstat:监控JVM的GC情况
jstat -gcutil <PID> 1000 10 # 每1秒采样一次,共采样10次
jmap:生成堆转储
jmap -dump:format=b,file=heap_dump.bin <PID>
Arthas:阿里开源的Java诊断工具
# 安装Arthas
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
# 使用thread命令查看线程情况
thread -n 3 # 显示CPU使用率最高的3个线程
# 3. 排查步骤
# 3.1 确认CPU使用率
首先使用top命令确认系统整体CPU使用率:
top
关注以下几个指标:
%us
:用户空间占用CPU百分比%sy
:内核空间占用CPU百分比%ni
:用户进程空间内改变过优先级的进程占用CPU百分比%id
:空闲CPU百分比%wa
:等待输入输出的CPU时间百分比
# 3.2 定位高CPU进程
在top命令中,按P键按CPU使用率排序,找出CPU使用率最高的进程,记录其PID。
# 或者使用ps命令
ps aux | sort -k3nr | head -10
# 3.3 分析进程内的线程
找到高CPU进程后,进一步分析该进程内的线程情况:
# 查看进程内的线程CPU使用情况
top -Hp <PID>
记录CPU使用率高的线程ID,将线程ID转换为十六进制:
printf "%x\n" <线程ID>
# 3.4 生成线程转储
对于Java应用,使用jstack生成线程转储:
jstack <PID> > thread_dump.log
在thread_dump.log文件中搜索之前转换的十六进制线程ID,找到对应的线程栈信息。
grep -A 30 "0x<十六进制线程ID>" thread_dump.log
# 3.5 分析GC情况
如果怀疑是GC问题导致的高CPU,使用jstat查看GC情况:
jstat -gcutil <PID> 1000 10
关注以下指标:
S0
、S1
、E
、O
、M
:各内存区域使用百分比YGC
、YGCT
:年轻代GC次数和时间FGC
、FGCT
:老年代GC次数和时间GCT
:总GC时间
如果频繁发生Full GC,可能是内存泄漏或内存配置不合理。
# 4. 常见原因及解决方案
# 4.1 代码问题
死循环或无限递归
- 症状:线程栈显示同一方法反复出现
- 解决方案:修复代码中的逻辑错误,添加适当的退出条件
算法效率低下
- 症状:CPU密集型计算占用大量资源
- 解决方案:优化算法,使用更高效的数据结构,考虑增加缓存
资源竞争
- 症状:多个线程争用同一把锁,导致上下文切换频繁
- 解决方案:减少锁粒度,使用并发容器,避免长时间持有锁
# 4.2 JVM问题
频繁GC
- 症状:jstat显示GC活动频繁,GC线程占用大量CPU
- 解决方案:调整JVM内存参数,增加堆内存,优化对象创建
JIT编译
- 症状:启动初期CPU使用率高,CompilerThread占用资源
- 解决方案:预热应用,使用AOT编译,调整JIT编译参数
# 4.3 系统问题
进程数过多
- 症状:系统进程数量异常增多
- 解决方案:检查是否有异常进程创建,限制进程数量
系统中断处理
- 症状:系统CPU使用率高,但用户进程CPU使用率不高
- 解决方案:检查硬件问题,更新驱动,调整系统参数
# 5. 实战案例
# 案例一:Java应用CPU飙升
现象:生产环境中一个Java应用CPU使用率突然飙升至100%,系统响应缓慢。
排查过程:
- 使用top命令确认Java进程CPU使用率接近100%
- 使用top -Hp命令找到占用CPU最高的线程ID
- 将线程ID转换为十六进制:
printf "%x\n" 12345
- 使用jstack生成线程转储并分析
- 发现问题线程在执行一个无限循环的操作
解决方案:修复代码中的无限循环问题,添加适当的退出条件和超时机制。
# 案例二:频繁GC导致CPU高负载
现象:应用运行一段时间后CPU使用率逐渐升高,响应变慢。
排查过程:
- 使用jstat发现Full GC频繁发生
- 使用jmap生成堆转储并分析
- 发现某个集合对象不断增长,没有释放
解决方案:修复内存泄漏问题,确保临时对象能够被及时回收。
# 6. 预防措施
# 6.1 监控告警
- 设置CPU使用率阈值告警,如连续5分钟超过80%触发告警
- 监控GC频率和时间,设置合理的告警阈值
- 监控线程数量,防止线程爆炸
# 6.2 性能测试
- 在上线前进行充分的性能测试和压力测试
- 模拟高并发场景,验证系统在极限情况下的表现
- 进行长时间的稳定性测试,发现潜在的资源泄漏问题
# 6.3 代码审查
- 重点关注循环、递归等可能导致CPU密集的代码
- 检查资源释放是否完整
- 避免使用低效算法处理大量数据
# 7. 总结
CPU使用率100%的问题排查是一个系统性工作,需要从操作系统、应用程序、JVM等多个层面进行分析。掌握相关工具和方法,可以帮助我们快速定位和解决问题,保障系统的稳定运行。
在实际工作中,建议建立标准的问题排查流程和工具集,提前做好监控和告警,做到早发现、早处理,避免问题扩大化。同时,持续优化代码质量和系统架构,从根本上减少高CPU问题的发生。