干货!!!线上CPU100问题排查的shell脚本

in 笔记 with 0 comment

废话篇

想要我的干货,能不能听听我的废话,哈哈

昨晚项目升级后今天早上一来公司没多久突然报警不断,pinpoint一路飙红,难得的CPU100问题出现了,4核的CPU达到了200%-300%使用率,每个节点都是如此。

经过运维那边反映,首先能肯定的是网站被爬虫了,但更能肯定的是我们的系统有严重的bug(废话了)。运维那边忙着封IP,我这边忙着排查问题,当时还比较早,很多同事都还没来。

我排查的方法当然也是拿着多年前至今也还广泛流传的网上那套方法,先top找高CPU的Java进程,再jstack把该进程线程栈信息打出来,反复几次对比找出长时间持续Runnable的线程定位其业务代码,巴拉巴拉xxxxx。但是这次没有定位不到具体哪一行业务代码,只发现一些mybatis的调用异常并且很多这种线程持续Runnable(如图)。
image.png

后来运维那边反馈已经封掉IP了,但是这个时候正常用户访问量也慢慢上来了,CPU虽然大幅度降低,也在40%~80%之间浮动(但我们系统平常值在20%左右)。看业务日志刷刷报一个REPLACE INTO操作的SQL异常,虽然没能从线程栈日志找出具体业务代码行数,但是结合线程栈大量的mybatis长时间Runnable日志和业务日志的这个REPLACE INTO报错,能肯定的是操作REPLACE INTO的地方导致的。

后来昨晚升级后负责这个功能的开发同事立即修复了这个问题后果然就天下太平了,最后我才知道原来REPLACE INTO会引起数据库死锁的问题,那为什么当时DBA反馈数据库正常没死锁呢?好吧,我一脸懵逼!

不废话了上干货,后面我们组Leader丢给我一个排查CPU100的shell脚本,他当着我面试了一下,排查效率比我刚刚那样手动排查不知高了多少,牛逼!

干货篇

#!/bin/bash

T=`ps -mp $1 -o THREAD,tid,time|sort -k 2 -nr|awk '{print $2","$8","$9}'|head -n 11|grep -v "-"`

for i in $T
do
consum=`echo $i |awk -F"," '{print $1}'`
tid=`echo $i |awk -F"," '{print $2}'`
dtime=`echo $i |awk -F"," '{print $3}'`
id=`printf "%x\n" $tid`
echo "线程消耗CPU:$consum% 运行时间:$dtime 线程id:$id" >>cpu_log.log
jstack $1 |grep $id -A 30 >>cpu_log.log
echo "">>cpu_log.log
echo "===========================================================================================" >>cpu_log.log

done

em~ 是时候该系统好好学学shell脚本了