现象:
李景发布laputa小需求,修改offer大图逻辑,调用search,重启不久出现cpu占用一度飙升到45左右。
背景:
排查过程:
what:
cpu占用过高,而且几乎暂用了全部的8核,肯定是线程死循环导致的。
查看java线程,cpu占用800-900%,查看java线程信息(top -H),发现部分线程cpu占用时间极高,取9288 lwp(内存占用在50%左右),查看堆栈信息,如下:
线程处于运行状态,但是始终没跳出HashMap.put方法,而303行是多线程触发死循环的代码点,初步定位hashmap死循环
查看几个暂用cpu高的线程都这样,并且线程始终不退出,基本定位hashmap的死循环问题。
注:中间时看cpu占用,每个线程占用没有达到100%,以为是不是死循环,一般死循环cpu占用都100%,后来发现,进入死循环状态的线程有多达69个,cpu不够用了,所以才出现占用不到100%,排查疏忽
why:
查看代码,发现代码hashmap挂起在org.apache.velocity.util.introspection.ClassMap的内部实现,调用一个cache属性,该属性是new hashmap,我记得早前看过velocity代码,这里的实现不是这样。
发现laputa,引用的velocity是1.6.1,看下代码,如下:
而velocity 1.6.4时改成如下:
通过MapFactory.create够造map,看了实现,默认构造concurrentHashMap
而我看的是1.7代码,实现更优雅,直接concurrentHashMap。
再询问应用负责人明东,之前没有遇到过类似问题,而这次应用开发时就出现过两次cpu占用100%,肯定是需求引入。
对比线上之前的rpm包,发现老的应用引用的都是1.6.4,包依赖问题。
和李景过下,用maven打印依赖数,cms包依赖velocity1.6.1,引入时没逐出,至此问题找到。
附件是jstack信息。
总结:
1.目前一个应用引用了太多技术干扰太多了,尤其对应用不是很熟悉,需要过滤各个框架问题
2.相信自己的经验,确定大体思路再继续排查,要不然没方向
补充:
velocity bug report:
https://issues.apache.org/jira/browse/VELOCITY-718