问题描述:
新版本灰度升级后,调用一个新接口,马上cpu会飙升到100+,并且实例再无响应,并且过几分钟后,cpu占用率会降下来,但是实例无法再提供服务,并且进程并没有死亡。
环境:
jdk:1.8
spring cloud: Daltson.RELEASE
排查办法:
- 1.查看此实例的进程号:
top
命令 - 2.查看此进程中占用最高的线程:
ps -mp pid -o THREAD,tid,time
- 3.将线程号转换成16进制:
printf "%x\n"
(上面命令看到的占用过高线程号) - 4.查看线程的堆栈信息:
jstack pid | grep tid
此时发现,占用最高的两个线程,全部是gc线程。 - 5.继续查看gc情况:
jstat -gcutil
,重启服务实例后,调用接口,cpu马上占用率飙高,用jstat命令查看到,这过程中fullGC达到300多次。明显此接口的一些操作引起了大量的对象堆积到内存中,导致内存爆掉了。 - 6.继续查看出现问题时,内存的占用情况,我选择查看内存中的对象的大小:
jmap -heap >heap.txt
jmap -histo > histo.txt
- 7.查看上面两个文件后终于发现了问题,调用此接口会产生大量的LinkedList对象和sharding-jdbc中的shardingPrepareStatment对象,这两个对象加起来将近占用了800m的内存,难怪会卡死。
问题原因:
后面就通过排查代码,跟踪数据,发现此问题是由于特殊的查询条件引起的sharding-jdbc出现了bug。
出现的原因如下代码示例:
<