1 引言
作为一名从事Java开发快一年的程序员,在线上经常碰到某个模块的Pod发出CPU与内存告警的问题,而这些问题会导致系统响应缓慢甚至是服务不可用。一般情况下可以通过重启或者调高Pod的资源量或者增加Pod数量暂时解决问题,但这是治标不治本的,只有找到问题发生的原因才能从根本上解决问题。那么在该如何快速定位到导致告警的原因呢?下面将汇总一下大致的处理思路。
一般来说导致Java程序CPU与内存冲高的原因有两种:
-
代码中某个位置读取数据量较大,导致系统内存耗尽,从而导致Full GC次数过多,系统缓慢。
-
代码中有比较耗CPU的操作,导致CPU过高,系统运行缓慢。
-
代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;
-
某个线程由于某种原因而进入WAITING状态,此时该功能整体不可用,但是无法复现;
-
由于锁使用不当,导致多个线程进入死锁状态,从而导致系统整体比较缓慢。
前两种情况出现的频率较高,可能会导致系统不可用,后三种会导致某个功能运行缓慢,但是不至于导致系统不可用。
对于第一种情况,本人曾经遇到过某个查全量数据的接口在某段时间被频繁调用导致内存耗尽、疯狂GC的情况:记一次GC导致的CPU与内存冲高的问题解决。
下面将总结一些具体的排查步骤。
2 分析工具
2.1 top命令查看CPU占用情况
PID为进程编号,COMMAND为其中执行命令,java即为要找的应用
-
top
: 展示所有进程占用情况 -
top -N num
: 展示CPU占用最高的num个进程
root@8d36124607a0:/### top
top - 14:01:23 up 1 day, 17:54, 1 user, load average: 0.00, 0.01, 0.05
Tasks: 101 total, 1 running, 100 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.8 us, 1.2 sy, 0.0 ni, 98.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 3782864 total, 1477524 free, 329656 used, 1975684 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 3181392 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
9 root 20 0 1031064 52580 19248 S 90.3 10.4 26:30.37 javacatalina.sh
root@8d361246