MQTT5 SessionExpiryInterval在ActiveMQ Artemis中未生效问题咨询
问题原因解析
1. 会话过期配置实际未匹配路由设置
从日志可以明确看到,客户端连接时向代理发送的sessionExpiryInterval是10秒,但你在Camel路由里配置的是60秒:
16-06-2023 07:38:09.866 [Thread-6 (activemq-netty-threads)] TRACE o.a.a.a.core.protocol.mqtt.MQTTUtil.logMessage - MQTT(null): IN << CONNECT protocol=(MQTT, 5), hasPassword=true, isCleanStart=false, keepAliveTimeSeconds=60, clientIdentifier=sendMachineDataToS3Dev, hasUserNAme=true, isWillFlag=false, sessionExpiryInterval=10, receiveMAximum=65535
这说明路由配置的参数可能被其他配置覆盖,或者Camel组件的参数传递存在问题。不过即使按日志里的10秒计算,代理也确实在7:38:26移除了会话:
16-06-2023 07:38:26.130 [Thread-0 (ActiveMQ-scheduled-threads)] DEBUG o.a.a.a.c.p.mqtt.MQTTProtocolManager.scanSessions - Removing state for session: sendMachineDataToS3Dev
2. 会话过期≠队列消息删除
MQTT 5的sessionExpiryInterval核心作用是控制代理保留会话状态的时长,包括:
- 未确认的QoS 1/2消息状态
- 客户端的非持久订阅关系
- 会话关联的临时数据
但它不会直接删除已经存储在队列中的消息。在ActiveMQ Artemis中,MQTT主题订阅会对应生成核心队列(通常命名为$mqtt.sub.xxx格式),QoS≥1的消息会持久化到该队列。即使会话过期被清理,只要队列本身存在,里面的消息就会保留,除非配置了队列级别的消息过期策略。
3. 重连后仍能消费的原因
当你用同一个clientId以cleanStart=false重连时,由于原会话已过期,代理会创建新会话并重新恢复订阅关系。此时队列中留存的未消费消息会被新会话的消费者拉取,所以你10-15分钟后重连仍能收到消息。
解决方案建议
- 排查Camel路由的
sessionExpiryInterval配置为何未生效,确保代理收到的参数和路由配置一致。 - 如果需要在会话过期后自动清理未消费消息,可配置:
- 发布消息时设置
messageExpiryInterval,让消息自身携带过期时间 - 为MQTT订阅对应的核心队列配置
expiry-delay,自动删除超时未消费的消息 - 使用MQTT 5的持久订阅特性,配合会话过期策略管理订阅生命周期
- 发布消息时设置
内容的提问来源于stack exchange,提问作者Ank
相关产品推荐
相关产品推荐

