1、问题现象
上游生产者服务在高并发下快速投递消息,一段时间后出现tomcat服务无响应,页面持续loading,后台无错误日志。
2、排查过程
2.1、日志分析
持续出现tomcat服务器OOM异常,tomcat重启。
开始以为因为tomcat参数设置不正确,修改tomcat参数后,系统运行一段时间问题依然存在。
2.2、jvm与操作系统监控
通过jvm和linux命令查看内存、cpu状态都处于正常。
2.3、线程dump
使用jstack打印线程dump,发现有线程死锁
2.4、源代码分析
根据线程死锁日志,分析源码发现是MQ死锁了。
2.5、MQ分析
查看MQ监控管理页面,发现磁盘空间占满,再查看MQ日志,确定由磁盘空间占满导致生产者阻塞。
3、原因分析
1、生产者采用异步投递方式
2、队列的下游并行消费者采用单线程消费
3、没有设置过期时间
4、解决思路
该问题的根本原因是mq中间件磁盘空间不足进而触发生产者流控机制,阻塞了上游服务,导致看似生产者服务被“挂起”的假死现象,实际上生产者只是被减速生产,等待mq的资源释放,一旦mq磁盘恢复正常,会继续投递消息到broker。消费端不受影响。 故关键在于提高下游消费能力、清理mq磁盘空间。
5、解决办法
1、针对磁盘空间的清理,可人为操作也可配置为对死信队列的自动清除策略
2、针对下游消费能力,可适当增加并行消费数concurrentConsumers,增加预取机制prefetchCount,优化ACK批量确认
3、针对生产者流控策略,可将默认阻塞配置为抛异常但非阻塞。