近期刚接手一个服务化应用,但每隔几天都会出现JVM进程僵死的情况。查看日志发现有大量的RocketMq Broker连接超时,起初怀疑是RocketMq broker不可用导致,但中间件同学反馈broker无异常。
应用异常日志
苦思无果后,使用jstack抓取JVM的线程堆栈,发现大量线程阻塞在获取RootLogger的锁
image.png
而该锁又被另一个消费者线程持有,但该线程处于RUNNABLE状态,由此判断不是死锁问题。该线程当前持有的锁仅仅是写入本地日志,怀疑是日志写入存在瓶颈。然而查看磁盘的利用率和对应的日志文件的增长速度,又否定了该判断。
image.png
随后使用jstat -gc指令分析JVM内存回收情况,发现老年代内存已经耗尽,FULL GC非常频繁,初步断定是JVM内存溢出。
image.png
使用jmap -histo指令发现业务对象OpenLogTO有350W未释放
排查业务代码发现,该对象通过开源框架EventBus写入ConcurrentLinkedQueue,并由另外一个线程从队列中获取并消费,而消费者此时已经由于异常而退出,导致OpenLogTO持续通过EventBus写入队列而不会被消费。
排查线上的疑难杂症,除了需要剖根问底的精神,严谨的思考能力,还需要对JVM的调优工具比较熟悉。分享一篇JVM性能调优工具使用 帮助大家了解JVM的常用调优工具。
image.png
网友评论