记一次死循环造成的CPU占用90%以上
2020-07-13 本文已影响0人
要取个帅气昵称
奇妙的盛夏,窗外也是蝉鸣鸟吟。正在办公室哈哈大笑的我,突然运维头像闪动,预感到大事不妙,运维告诉我说某批机器CPU负载太高是Java进程造成的。
1.打开对应机器链接 top 命令查看
image.png
不看不知道,一看我浑身冒冷汗,呆呆的看了几秒发现CPU还是下不去。这下是摊上事了
- ps -mp 46112 -o THREAD,tid,time 查看当前PID中的线程情况
image.png
乖乖。这个线程持续占用了CPU 90%以上。必须紧急修复
转成16进制
printf "%x\n" 46198 得到 b476
- jstack -l 46112 > /home/name/js.log中查看情况
image.png
可以看到是某个Java文件中的线程run方法中持续占用CPU
- 追踪到代码中查看
image.png
查看代码可以看到,这是一个典型的生产者-消费者模型的代码,但是我当时纳闷了怎么循环是这么写的,take()本身自带阻塞属性,为什么没有阻塞?查看日志,发现那段时间blockingQueue根本没有任何数据进来,这个就造成了if (CollectionUtils.isNotEmpty(blockingQueue)) 始终判断是true,在服务器上形成了死循环,这下问题找到了就好解决了。删除第一行if判断就行了
总结: 代码没什么好说的,这是严重的问题点,并且在处理过程记录数据中没有加入数据备份,这次还好是CPU占用过高,但是下次如果是宕机,blockingQueue中的没来得及消费的数据就丢失了。所以在生产代码的同时,我们程序员应该考虑多种场景的处理,只有自身基础牢固了,这类问题都可以快速的定位问题及解决问题