线上环境CPU使用率飙升,如何排查
1.CPU飙升的常见原因
1. 代码层面问题
- 死循环:错误的循环条件导致无限循环
- 递归过深:没有正确的终止条件
- 算法效率低:O(n²)或更高时间复杂度的算法处理大数据集
- 频繁GC:内存泄漏导致频繁垃圾回收
2. 并发问题
- 线程阻塞:过多的线程等待资源(锁、数据库连接等)
- 线程爆炸:创建过多线程,上下文切换开销大
- 锁竞争:激烈的锁竞争导致线程频繁挂起和唤醒
3. 外部依赖问题
- 数据库:慢查询、全表扫描、缺少索引
- 外部API:响应变慢或阻塞
- 网络IO:网络延迟或带宽瓶颈
4. 资源问题
- 内存不足:频繁的GC操作消耗CPU
- 磁盘IO:大量的磁盘读写操作
5. 配置问题
- JVM参数:不合理的堆大小、GC参数等
- 线程池配置:不合理的线程池大小
2.模拟线上环境cpu飙升
条件准备
主要是用于演示,当线上环境出现cpu飙升时,怎么去排查问题,因此此处就使用死循环去构造该场景
如上所示,项目结构也是及其的简单,定义一个接口,用于访问,触发死循环的执行,用于构造cpu飙升的场景
代码打包部署
将项目打包为jar包,在虚拟机上部署运行
# 参考命令
java -jar high-cpu-1.0-SNAPSHOT.jar
# 后台运行
nohup java -jar high-cpu-1.0-SNAPSHOT.jar &
运行之后检查下是否成功
然后对接口发起请求http://ip:10003/high/cpu,执行while循环
3 排查步骤
获取所有进程执行信息
首先使用top命令,查看线程的占用情况
[root@mycentos local]# top
可以确认PID为93992的进程,占用cpu最高
查看指定进程的各线程的执行信息
使用命令,查看当前进程中的线程的信息
ps H -eo pid,tid,%cpu | grep 93992
由上图可知线程id为94012的线程的占用率最高
将线程号转为16进制,并记住该16进制
printf "%x\n" 94012
最终定位
[root@mycentos local]# jstack 93992
执行jstack 93992 可以根据线程 id 找到有问题的线程,进一步定位到问题代码的源码行号
由此可以定位到红框中可能出现错误的代码信息,进而进一步解决问题