从 2.6.3 到 2.6.8,mica-mqtt 连续发布了多个修订版本。与增加新功能相比,这轮更新更关注 MQTT 系统的基本盘:消息能否稳定转发、客户端断线后能否正确重连、过期会话能否及时清理、代理接入是否可靠,以及 MQTT 5.0 协议交互是否兼容。
目前最新正式版是 2.6.8。仍在使用 2.6.3 的项目,不应只比较 API 变化,还要把这几个版本看成一组累计稳定性修复,并围绕真实连接生命周期完成升级验证。
为什么这些修复会直接影响生产系统
MQTT 的故障往往不是“服务完全不可用”,而是更难发现的局部异常。例如,连接看起来仍然存活,但部分消息没有继续转发;网络恢复后客户端反复重连;会话已经失效,服务端资源却没有及时释放。
本轮更新集中覆盖了几条容易互相影响的链路:
- 消息转发:需要关注订阅匹配、消息到达率以及重复投递情况。
- 断线重连:不仅要确认客户端重新建立 TCP 连接,还要验证订阅和消息流是否恢复。
- 会话清理:异常断开、正常退出和超时过期可能走不同路径,任何遗漏都会积累资源。
- 代理接入:当 MQTT 服务位于负载均衡器、网关或 TCP 代理之后时,连接地址和生命周期处理更复杂。
- MQTT 5.0 兼容:属性、原因码和会话语义比早期协议版本更丰富,边界条件也更多。
这些问题通常会在弱网、频繁上下线、大量长连接或混合协议版本环境中被放大。因此,升级测试不能只做一次连接和发布,还要主动制造断网、重启和会话过期。
升级时不要只替换版本号
如果项目通过 Maven 引入 mica-mqtt,可以先在父 POM 或依赖管理中把版本集中调整为 2.6.8。下面使用属性名作为示例;实际依赖坐标和模块名称应保留项目当前配置,只修改版本值:
<properties>
<mica-mqtt.version>2.6.8</mica-mqtt.version>
</properties>
修改后检查最终解析出的依赖,避免某个子模块仍然通过传递依赖使用旧版本:
mvn -q dependency:tree -Dincludes='*mica-mqtt*'
Gradle 项目可以执行:
./gradlew dependencies | grep -i -A 3 -B 3 'mica-mqtt'
这里的目标不是确认构建成功,而是确认所有运行节点最终加载的版本一致。滚动升级期间,如果新旧节点同时处理会话和消息,应额外观察跨节点转发、连接迁移与会话清理行为。
可以这样搭建一组重连与转发冒烟测试
下面的命令使用 Eclipse Mosquitto 客户端作为测试工具,用于验证升级环境的外部行为。它不依赖 mica-mqtt 的 Java API,因此也适合放进部署后的验收脚本。
运行前,把 MQTT_HOST、MQTT_PORT、用户名和密码改成测试环境参数。如果测试环境没有认证,可以删除两个认证参数。
export MQTT_HOST=127.0.0.1
export MQTT_PORT=1883
export MQTT_USER=tester
export MQTT_PASSWORD='change-me'
export MQTT_TOPIC='upgrade/268/smoke'
mosquitto_sub \
-h "$MQTT_HOST" \
-p "$MQTT_PORT" \
-u "$MQTT_USER" \
-P "$MQTT_PASSWORD" \
-V mqttv5 \
-t "$MQTT_TOPIC" \
-q 1 \
-c \
-i mica-upgrade-subscriber \
-v
保持订阅端运行,再打开另一个终端连续发布带序号的消息:
for i in $(seq 1 100); do
mosquitto_pub \
-h "$MQTT_HOST" \
-p "$MQTT_PORT" \
-u "$MQTT_USER" \
-P "$MQTT_PASSWORD" \
-V mqttv5 \
-t "$MQTT_TOPIC" \
-q 1 \
-m "message-$i"
sleep 0.1
done
测试过程中主动中断订阅客户端的网络,等待几秒后恢复,然后重新执行相同的订阅命令。至少检查以下结果:
- 客户端能够重新连接,而不是进入高频重连循环。
- 恢复连接后能够继续收到新消息。
- QoS 1 场景没有出现无法解释的大量丢失或重复。
- 相同客户端标识重新接入时,会话行为符合业务配置。
- 服务端连接数和会话数最终能够回落,没有持续累积。
-c 表示请求持久会话语义,但 MQTT 5.0 下的最终会话保留行为还会受服务端配置和会话过期间隔影响。测试时应使用与生产环境一致的参数,而不是根据一次命令结果推断所有会话场景。
把代理和故障恢复纳入验证范围
如果生产环境通过 Nginx Stream、HAProxy、云负载均衡器或 Kubernetes Service 暴露 MQTT 端口,直连测试不能代替代理链路测试。可以这样实践:分别对服务端直连地址和生产入口执行同一组发布、订阅、断网与重连用例,再比较连接恢复时间和消息结果。
同时记录以下指标:
- 当前连接数、连接创建速率和异常断开速率;
- 重连次数与连续重连失败次数;
- 发布、转发和消费消息计数;
- 会话总数、过期会话清理数量和清理延迟;
- JVM 堆内存、直接内存、线程数和文件描述符;
- MQTT 5.0 客户端收到的原因码和断开原因。
如果升级后连接数正常,但会话数持续增长,问题可能仍在清理路径;如果重连成功而消息没有恢复,应继续检查订阅恢复和会话状态,而不能只看 TCP 连接指标。
上线前的决策清单
从 2.6.3 升级到 2.6.8 的价值主要来自累计修复,而不是新增接口。更稳妥的上线方式是先在压测或灰度环境复现生产连接模型,再逐步扩大节点比例。
上线前应确认:
- 所有模块和镜像实际使用 2.6.8,没有遗留旧依赖;
- MQTT 3.x 与 MQTT 5.0 客户端都完成基本互通测试;
- QoS 0、QoS 1 以及业务实际使用的 QoS 等级分别验证;
- 弱网、代理断开、Broker 重启和客户端重启均纳入测试;
- 会话过期后,连接、订阅和相关资源能够按预期释放;
- 灰度阶段已设置连接数、重连率、消息差异和资源增长告警;
- 保留可执行的回滚方案,并避免在未验证会话兼容性的情况下频繁来回切换版本。
对 MQTT 基础设施而言,稳定性升级的验收标准不是“服务启动成功”,而是在连接不断变化、网络偶尔失败、客户端版本并存的情况下,消息和会话仍然保持可解释、可观测、可恢复。