记一次ActiveMQ的异常排查

一、异常背景

做一个小项目时,选择使用 ActiveMQ 作为中间件,负责项目内各组件的通信。

刚部署时,整个项目运行正常。运行 N 天后,发现 ActiveMQ 出乎意料地自动重启,进而导致队列中未来得及消费的数据丢失。

刚开始,以为是配置文件 activemq.xml 的问题,但是仔细核查后,发现没有什么明显的错误配置。然后,怀疑是否是 ActiveMQ 版本的问题,因此另选了一台测试机器进行其他版本的测试,结果发现还是出现同样的异常现象。至此,基本可以排除配置和版本的问题,只能从日志或其他途径,去排查问题的根源。

二、异常排查

寻找问题时,首先能想到的自然是排查日志文件。但是在查看 ActiveMQ 日志的时候,很诡异的现象出现了。ActiveMQ 每一次异常重启时,日志并没有输出任何内容,只有输出正常启动时所展示的堆栈信息。这一下问题就变得比较棘手了,没有异常抛出,那么该如何定位问题的根源?

考虑过阅读 ActiveMQ 的源码,来推理问题的产生原因,但因为项目相对较急,只能作罢。

束手无策之际,突然想到是否会与机器内存有关?毕竟项目程序所在机器的配置较低。思虑至此,马上使用 jstatjmap 观察 ActiveMQ 的 JVM 情况。然后,再一次发现了诡异的现象。ActiveMQ 运行期间,每一次老年代内存区耗尽触发 FGC 时,老年代的内存并没有释放,反而是申请了更多的内存空间,因此随着 ActiveMQ 的运行时间增长,老年代所占空间也越来越大,直至达到限制的最大内存时,ActiveMQ 崩溃重启。

这一下,问题的根源总算是找到了,但是,新的问题也随之而来。由于项目较小,队列中的消息都能够及时被消费者消费掉,理论上不存在内存持续增长的可能,那么,究竟是什么造成了老年代内存占用不断增加?再次检查了一遍配置文件,依旧毫无收获。

此时,似乎已山穷水尽。突然,一个凭空而现的想法提供了新的思路。会不会问题压根就不是出在 ActiveMQ 本身,而是出现在客户端代码?思路一通,马上查看了项目中与 ActiveMQ 相关的代码,发现了一个可疑的地方。代码中使用 Session 收发消息后,并没有 close 掉。那么,会不会有这种可能?由于客户端没有关闭会话,服务端会一直保持着这个 Session,导致该 Session 下持有的对象一直存在着引用,不会被 GC 回收,进而导致内存不被释放,最后引发崩溃。这样一想,一切似乎都说得通了。在客户端代码中添加上 Session 的 close 方法,更新到集群后,再一次持续观察 ActiveMQ 的状态。这一次,一切都恢复了正常,老年代内存在 FGC 触发后成功释放,ActiveMQ 也不再莫名其妙重启了。

至此,问题总算解决。然而,内中缘故,还不是理解很透彻,后续还需抽空深入了解才是。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值