如何排查Apache ActiveMQ Artemis 2.16.0随机消息丢失问题
排查优先级步骤
第一优先级:代码与配置逻辑校验(最高优先,先修复明确错误)
- 修正JMS容器配置冲突:你当前同时配置了
factory.setSessionTransacted(true)和Session.CLIENT_ACKNOWLEDGE,不符合JMS规范——会话开启事务时客户端确认模式会直接失效,Spring仅会根据消费方法是否抛出未捕获异常,决定提交或回滚消费事务。建议保留事务模式,删除CLIENT_ACKNOWLEDGE配置,避免逻辑歧义。 - 校验消费事务边界一致性:你当前的消费方法捕获所有异常后未向外抛出,只要catch块执行完成无异常,Spring会直接提交消费事务,原消息会从源队列永久删除。如果
responseSender.send(otherQueue, message, ex)执行失败但内部吞了异常未抛出,就会出现原消息已删除、转发消息未入队的丢消息场景。需保证转发消息的操作和原消息的消费操作在同一个JMS事务内,要么同时成功要么同时回滚。 - 补全全链路消息ID日志:所有消息生产、消费、转发、异常的日志都必须打印
JMSMessageID,可直接根据ID跟踪单条消息的全链路流转。 - 检查生产端消息持久化配置:如果生产端发送消息时设置了
NON_PERSISTENT属性,消息不会写入broker磁盘,broker重启后消息会直接丢失,也不会进入DLQ。 - 校验重试配置:你当前
broker.xml未配置max-delivery-attempts参数,Artemis 2.16版本该参数默认值为10,但SpringDefaultJmsListenerContainerFactory自带的重试机制默认重试次数为1,你日志中仅出现1次重试大概率是Spring侧重试耗尽,需调整Spring重试模板配置,和broker端重试规则对齐。
第二优先级:Broker侧消息流转排查
- 开启Artemis消息轨迹功能:在
broker.xml的core节点下添加<message-trace enabled="true"/>,开启后所有消息的全生命周期(生产、入队、出队、转发、入DLQ、过期、删除)都会记录到broker日志中,可直接根据JMSMessageID查询消息最终去向。 - 排查broker运行日志:检查丢消息对应时间点是否存在磁盘IO异常、磁盘使用率超过90%阈值、内存溢出、Critical Analyzer触发进程终止等异常记录,你当前配置的
critical-analyzer-policy=HALT,触发后会直接终止broker进程,若此时有未完成的事务可能出现消息状态不一致。 - 检查过期队列:如果生产端设置了消息
timeToLive属性,消息过期后会进入ExpiryQueue而非DLQ,需排查该队列是否存在丢失的消息。 - 核对队列统计数据:对比源队列的总入队数、总出队数、死信数、转发数的差值,确认消息是在消费端丢失还是broker内部流转丢失。
第三优先级:场景复现与边界验证
- 模拟网络闪断、broker临时不可用的异常场景,验证转发失败时的事务回滚逻辑是否符合预期,是否会出现丢消息问题。
- 关闭自动创建队列配置,避免配置错误导致消息被转发到自动创建的错误队列中。
可用排查工具
- Artemis自带管理控制台:可查询所有队列的消息数量、消息详情,浏览DLQ、ExpiryQueue的内容,查看队列统计指标。
- Artemis CLI命令行工具:通过
artemis queue stat命令可导出所有队列的历史统计数据,对比入队出队差值定位丢消息范围。 - JmsToolbox:可直接浏览所有队列的消息内容,支持导出消息用于排查。
- 日志检索工具:通过grep、ELK等工具,根据
JMSMessageID检索全链路日志,跟踪单条消息的流转路径。
内容的提问来源于stack exchange,提问作者miroana
相关产品推荐
相关产品推荐

