赞
踩
近期打算整理一系列线上问题排查的文章,也做备忘用吧,虽然问题排查都有印象了,但是真遇到线上问题难免紧张,万一步骤弄错了就耽误时间了
CPU飙高问题一般通过以下几个步骤来排查
先来看看步骤1,定位cpu占比高的Java进程比较简单,可以直接通过top命令或ps命令,但由于top命令比较简单,不像ps命令有过多的参数,所以大多数会优先使用top命令。其实现在线上大多是每个服务都有单独的容器了,所以CPU飙高大部分是你的服务有问题(少数情况下有一些插件异常导致的CPU过高,也需要排查少部分情况,做到严谨)
详细描述
一:找到最耗CPU的进程
执行top -c,显示进程运行信息列表
输入P,进程按照CPU使用率排序
如图所示,最耗CPU的进程PID为32761
二:找到最耗CPU的线城
top -Hp 32761 显示一个进程的线城运行信息列表
输入P,线程按照CPU使用率排序,这里没图了,假设最耗CPU的线程PID为10704
三:查看堆栈信息,定位线程在做啥,定位对应代码
1.将线程PID转为16进制
printf "%x\n" 10704
得到对应的16进制是29d0
2. 接着查看堆栈,找到线程
jstack 32761|grep '29d0'
打印进程堆栈,通过线程ID过滤得到线程堆栈
最后根据堆栈里的信息,找到对应的代码即可
以上几个步骤是没问题的,但是真到线上排查时显得步骤有些多,毕竟出问题的时候是要争分夺秒的,最好是通过一个脚本就能完成上述所有操作
入参只有一个就是Java的pid,如果没有入参那么默认会取最耗CPU的Java进程
- #!/bin/bash
- if [ -z "$1" ]; then
-
- ### 1.先找到消耗cpu最高的Java进程 ###
-
- pid=`ps -eo pid,%cpu,cmd --sort=-%cpu | grep java | grep -v grep | head -1 | awk 'END{print $1}' `
-
- if [ "$pid" = "" ]; then
-
- echo "无Java进程,退出。"
-
- exit
-
- fi
-
- else
-
- pid=$1
-
- fi
- curTime=$(date +%Y%m%dT%H:%M:%S)
- dumpFilePath="/tmp/pid-${pid}−${curTime}.jstack"
-
-
- echo -e "java 进程ID为 $pid" > ${dumpFilePath}
- ps -ef|grep ${pid} >> ${dumpFilePath}
- topThreadId=`top -b -n 1 -Hp ${pid}|grep java|head -n 1|awk '{print $1}'`
- cpuUsage=`top -b -n 1 -Hp ${pid}|grep java|head -n 1|awk '{print $9}'`
- echo -e "最耗cpu的使用率为 $cpuUsage">>$dumpFilePath
- topThreadId16=`printf "%x" ${topThreadId}`
- topThreadId16ThreadName="nid=0x${topThreadId16}"
- echo -e "最耗cpu的java线程ID 16进制为 $topThreadId16ThreadName">>$dumpFilePath
- jstack -l ${pid} >>$dumpFilePath
- #threadDe -e tail=`jstack ${pid}|grep ${topThreadId16} -C 10`
- #echo "$threadDetail"

这样就能实现一个脚本记录所有信息了,大大节省线上排查问题的时间,也不容易看错
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。