生产服务器cpu占用100%排错步骤

195 阅读1分钟

argus(阿格斯) 报警cpu占用100%,立马使用常规定位方法: 1, top -H-p命令找出cpu占用最高的进程
2,jsp -l 进一步定位出进程编号
3,ps -mp <进程号> -o thread,tid,time 定位出具体线程 发现进程下的线程资源占比根本就不高,因此不能定位到具体线程的堆栈信息,怀疑是在做FULL GC,查看进程GC回收情况

jstat -gcutil <进程号> 3000

gc.png 回收正常,定位不到问题,只能等到下一次报警再打印堆栈信息

jstack -l <进程号> > /<输出的文件名称>

将进程号转成16进制,在文件中搜索

gc.png 确定是在做GC回收导致的cpu占比100%,立即用jmap命令输出加载类的内存占用情况

jmap -histo:live <进程号> > /<输出的文件名>

gc.png 定位到具体的数据表对象,全量查表信息将内存打满,触发FULL GC,但具体是那个子业务那段逻辑引发的,需要写个shell脚本,找出对应线程号

#!/bin/bash  
cd /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.232.b09-0.el7_7.x86_64/bin  
APP_PID_TEMP=$(./jps -l | grep wom )  
eval "$(echo "$APP_PID_TEMP" | awk '{ printf("pid=%s;pidname=%s",$1,$2)}')"  
echo "加载的项目是$pidname,进程ID是: $pid"  
APP_PID=$pid  
  
topJavaId=`top -b -n 1 -Hp ${APP_PID}|grep java|head -n 1|awk '{print $1}'`  
cpuUsage=`top -b -n 1 -Hp ${APP_PID}|grep java|head -n 1|awk '{print $9}'`  
echo "最耗cpu的使用率为 $cpuUsage"  
topJavaId16=`printf "%x" ${topJavaId}`  
topJavaId16ThreadName="nid=0x${topJavaId16}"  
echo "最耗cpu的java线程ID 16进制为 $topJavaId16ThreadName"  
threadDetail=`./jstack ${APP_PID}|grep ${topJavaId16} -C 10`  
echo Thread Detial "$threadDetail"

或者拼手速

1, top -H -p 命令找出cpu占用最高的进程  
2,jps -l 进一步定位出进程编号  
3,ps -mp <进程号> -o thread,tid,time 定位出具体线程 耗时最多的即是有问题的线程  
4,线程Id 转为16进制(linux 中输出的为10进制)  
5,打印内存信息 jstack <进程id> | grep 小写16进制线程id -A60

即能够定位出具体代码位置