针对Java应用,我结合我们的docker环境写了一个容器cpu飙升问题精确排查步骤(注:有的镜像过于精简,一些命令工具是缺失的,所以要想实施以下方案,容器中的linux常用命令安装是需要解决的)
容器必备命令
top -Hp jvm进程ID 找到cpu占用最高的 jvm 线程ID
jstack jvm进程ID 导出java线程栈信息
printf “%x\n” 线程ID 将10进制数字转换成16进制数
下面是我在dev环境的测试情况
1、top命令查出Java进程ID,如下图为 54
2、查出java进程内 哪个线程ID占用cpu最高
top -Hp 54
如下图最高的是线程ID为78的线程
3、将线程ID转换成16进制
printf "%x\n" 78
4、抓取对应线程堆栈信息
jstack 进程号 | grep nid=0x+16进制线程号 -A 100
jstack 54 | grep nid=0x51 -A 100
如下图就找到了最高的线程堆栈信息,进一步可以找到程序里的类和方法信息
5、下面自动化脚本
echo '----------begin----------'
count=1
if [[ x$1!=x ]]; then
#statements
count=$1;
fi
jvm_pid=$(top -n 1 | grep java | awk '{print $2}' )
echo 'jvm pid = '$jvm_pid
for i in $(seq 1 $count); do
#statements
max_cpu_tid=$( top -Hp $jvm_pid -n 1 | awk 'NR==8' | awk '{print $2}' )
echo 'cpu max java thread tid = '$max_cpu_tid
tid16=$(printf "%x\n" $max_cpu_tid)
echo 'tid16 = '$tid16
jstack $jvm_pid | grep nid=0x$tid16 -A 100
echo '---------------------------------------------------------'
sleep 1s
done
echo '----------end----------'