线上CPU飙升排查
作者:互联网
线上CPU飙升排查
目录准备一份代码
public class Main {
public static void main(String[] args) {
int i = 0;
while (true) {
i++;
i--;
}
}
}
步骤
top命令找到对应进程
top
找到占用最高的线程
方法1
top -Hp 506
方法2
ps -mp 506 -o THREAD,tid,time
linux下的线程号是10进制,而jdk自带工具中的线程号使用的是16进制,我们需要先把它转换成16进制
将线程号转换成16进制
print "%x\n" 507
# 1fb
使用jdk的工具jstack查看堆栈信息
-A100表示最多显示100行
jstack 506 | grep 1fb -A100
我们看到上面直接定位到了,main方法的第7行
如果是那种多线程代码,我们要给线程池中的线程命名,这样便于我们排查到对应代码,这里仅仅作为示范
cpu飙升可能原因
1. 超大对象频繁移动或者创建
超大对象频繁在年轻代中移动,消耗CPU性能
解决思路
- 考虑直接将对象放到老年代
- 对象能复用则复用,可以使用对象池,避免频繁创建大对象
2 .内存消耗过大,导致Full GC次数过多
我们会在top命令中排查到GC线程的CPU很高,
这样可以使用jstat工具查看GC次数,确认是否为Full GC过多
jstat gcutil 进程id 间隔时间 统计次数
# 样例 jstat -gcutil 506 10 10
也可以通过查看老年代的情况判断
jdk 8使用如下命令
jmap -heap 进程id
jdk 9以后使用如下命令
jhsdb jmap --pid 进程id --heap
➜ emmith jhsdb jmap --pid 506 --heap
Attaching to process ID 506, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 17.0.3+7-LTS
using thread-local object allocation.
Garbage-First (G1) GC with 8 thread(s)
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 3309305856 (3156.0MB)
NewSize = 1363144 (1.2999954223632812MB)
MaxNewSize = 1983905792 (1892.0MB)
OldSize = 5452592 (5.1999969482421875MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 22020096 (21.0MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 2097152 (2.0MB)
Heap Usage:
G1 Heap:
regions = 1578
capacity = 3309305856 (3156.0MB)
used = 14659584 (13.98046875MB)
free = 3294646272 (3142.01953125MB)
0.4429806321292776% used
G1 Young Generation:
Eden Space:
regions = 6
capacity = 25165824 (24.0MB)
used = 12582912 (12.0MB)
free = 12582912 (12.0MB)
50.0% used
Survivor Space:
regions = 0
capacity = 0 (0.0MB)
used = 0 (0.0MB)
free = 0 (0.0MB)
0.0% used
G1 Old Generation:
regions = 2
capacity = 186646528 (178.0MB)
used = 2076672 (1.98046875MB)
free = 184569856 (176.01953125MB)
1.112622893258427% used
解决思路
- 增大堆空间,增大老年代
- 将对象放到堆外内存,减少GC
- 代码里面可能有System.gc()显示调用,禁用此功能
3. 死循环等CPU密集型代码
代码中可能存在死循环、或者CAS使用不当、或者无线递归
解决思路
- 优化代码逻辑,尽量避免无线递归和死循环
- 减少CAS次数,或者适当让线程睡眠,如果线程资源竞争特别激烈的情况,将CAS改为使用锁,避免太多的CPU空转
4. 死锁
死锁可以在jstack命令中看到,grep deadlock可以排查是否有死锁
解决思路
如果存在死锁,考虑代码逻辑问题,避免不正确的锁申请顺序
5. 流量激增
集群中别的负载均衡的机器都挂了,请求全部打到某条机器上,导致CPU飙升
解决思路
- 限流,熔断降级
- 异地多活,保证高可用
参考
https://www.cnblogs.com/dennyzhangdd/p/11585971.html
https://juejin.cn/post/6844904089705250829
标签:used,MB,代码,排查,线程,线上,GC,CPU 来源: https://www.cnblogs.com/emmith/p/16467328.html