迁移至Spring Boot 3后Artemis生产者监听器的重复投递抑制与DLQ问题
Artemis主备集群跨客户端通信问题排查与解决
背景信息
- 集群环境:Artemis 2.17.0主备集群
- 通信模块:
- 遗留消费端:基于ActiveMQ Classic的OpenWire JMS库,部署消息监听器
- 生产端:Spring Boot 3应用,使用
artemis-jakarta-client(从Spring Boot 2.7的artemis-jms-client迁移而来)
- 异常症状:
- 迁移到Spring Boot 3后,仅应用启动后的第一条消息能被正常消费
- 后续所有消息直接进入死信队列(DLQ)
- 遗留监听器日志持续出现
suppressing duplicate delivery on connection警告
问题根源分析
这个警告的本质是Artemis的重复消息投递抑制机制被触发,核心原因是Jakarta JMS客户端与OpenWire客户端的消息处理逻辑不兼容,具体触发点:
- Jakarta JMS规范下的消息ID格式和OpenWire客户端预期格式不一致,导致Artemis误判消息重复
- 生产端与消费端的ACK模式不匹配,Artemis认为消息未被正确确认,重复投递后触发抑制规则,最终路由到DLQ
- 主备集群环境下,Jakarta客户端的连接复用逻辑和OpenWire监听器的会话状态冲突,导致后续消息投递上下文异常
解决方案步骤
1. 调整Artemis服务端重复检测配置
在Artemis的broker.xml中,针对目标队列或全局关闭/放宽重复消息检测:
<configuration> <core> <!-- 全局关闭重复检测(若业务允许) --> <message-duplicate-detection>false</message-duplicate-detection> <!-- 或针对特定队列精细化配置 --> <address-settings> <address-setting match="your.target.queue"> <message-duplicate-detection>false</message-duplicate-detection> <!-- 调整最大投递次数,避免消息快速进入DLQ --> <max-delivery-attempts>3</max-delivery-attempts> </address-setting> </address-settings> </core> </configuration>
如果必须保留重复检测,可尝试调大duplicate-detection-window-size参数,延长检测窗口,减少误判概率。
2. 统一生产端与消费端的ACK模式
在Spring Boot 3生产端显式指定ACK模式为AUTO_ACKNOWLEDGE,和遗留OpenWire监听器保持一致:
Java配置方式
@Configuration public class ArtemisProducerConfig { @Bean public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) { JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory); // 显式设置ACK模式为自动确认 jmsTemplate.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE); return jmsTemplate; } }
配置文件方式
在application.properties中添加:
spring.artemis.jms.acknowledge-mode=auto
3. 检查遗留OpenWire客户端的会话配置
确保遗留消费端的会话ACK模式配置正确,避免手动ACK遗漏导致的异常:
// 示例:创建自动确认模式的会话 Connection connection = openWireConnectionFactory.createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
4. 升级Artemis版本(可选)
Artemis 2.17.0版本相对老旧,后续稳定版本(如2.20.x及以上)对Jakarta JMS与OpenWire的兼容性做了针对性优化,升级后可能直接解决该问题。
验证步骤
- 重启Artemis集群及两个应用
- 连续发送多条测试消息,检查是否全部被正常消费,无消息进入DLQ
- 查看遗留监听器日志,确认
suppressing duplicate delivery on connection警告不再出现
内容的提问来源于stack exchange,提问作者daniele andreoli
相关产品推荐
相关产品推荐

