4. MQTT核心机制
MQTT 之所以适合车联网,不仅因为它报文小、开销低,更因为它用一套清晰的机制解决了“车怎么上线、消息怎么路由、消息丢不丢、离线后怎么办”这四个工程问题。本节围绕连接建立、主题与通配符、QoS 等级、保留消息与遗嘱消息展开,这五项机制共同构成了 MQTT 会话的骨架。
一、连接建立:从 TCP 到会话
MQTT 建立在 TCP 之上,客户端与 Broker 之间必须先完成 TCP 三次握手,再发送 CONNECT 报文。CONNECT 中携带的关键参数决定了后续会话行为:Client ID 用于标识客户端;Clean Session(MQTT 3.1.1)或 Clean Start(MQTT 5.0)决定是否复用历史会话;Keep Alive 定义心跳周期;Will 主题与内容用于遗嘱消息;用户名密码用于鉴权。
Broker 收到 CONNECT 后返回 CONNACK,其中 Session Present 标志告诉客户端“服务端是否保留了你的旧会话”。若 Clean Session=0 且 Session Present=1,客户端可继续使用未确认的 QoS 1/2 消息和订阅关系;若为 0,则一切从零开始。车联网中,车载 T-Box 通常设置 Clean Session=0,以便弱网重连后不丢失订阅和未完成消息。
CONNECT
Client ID: TBOX_京A12345
Clean Session: 0
Keep Alive: 60s
Will Topic: vehicle/京A12345/status
Will Payload: {"online":false}
Will QoS: 1
Will Retain: true
CONNACK
Session Present: 1
Return Code: 0 (Accepted)
二、主题与通配符:消息路由的地址系统
MQTT 主题是分层字符串,用“/”分隔,例如 vehicle/京A12345/telemetry/speed。主题本身不要求预先创建,Broker 按层级匹配订阅。通配符有两种:+ 匹配单层,# 匹配多层且只能出现在末尾。例如 vehicle/+/telemetry/speed 可匹配任意车辆的 speed 数据;vehicle/京A12345/# 可匹配该车所有子主题。
工程上要避免用 # 订阅全量主题,否则 Broker 和客户端都会被无关消息淹没。车联网常见做法是按“车辆 ID / 业务域 / 指标”三层设计,如 vehicle/{vin}/telemetry/{signal},既便于权限隔离,也便于用通配符做批量订阅。
三、QoS 等级:消息可靠性的三档选择
QoS 决定消息投递的可靠程度,而不是“消息重要性”。QoS 0 最多一次,发完即忘,适合高频遥测;QoS 1 至少一次,可能重复,适合指令下发;QoS 2 恰好一次,通过四次握手保证不重不漏,但开销最大,适合计费、关键配置等场景。
| QoS | 投递语义 | 报文交互 | 典型车联网场景 |
|---|---|---|---|
| 0 | 最多一次 | PUBLISH | 车速、转速等高频遥测 |
| 1 | 至少一次 | PUBLISH / PUBACK | 远程控车指令、告警上报 |
| 2 | 恰好一次 | PUBLISH / PUBREC / PUBREL / PUBCOMP | OTA 结果、计费凭证 |
注意:QoS 是端到端协商结果,实际生效等级取发布与订阅两者中的较小值。若发布用 QoS 2、订阅用 QoS 0,最终按 QoS 0 投递。因此排查“消息为什么丢了”时,必须同时检查发布端和订阅端的 QoS 设置。
四、保留消息与遗嘱消息:离线状态的两把钥匙
保留消息(Retained Message)由发布者设置 retain=true,Broker 会为该主题保存最后一条保留消息。新订阅者一旦订阅该主题,立即收到这条消息,无需等待下一次发布。车联网中常用于“车辆最新状态”:新上线的监控端订阅 vehicle/+/status 后,立刻拿到每辆车最后已知的在线状态。
遗嘱消息(Will Message)在 CONNECT 时注册,当客户端异常断开(未发送 DISCONNECT)时,由 Broker 代为发布。它常用于“离线告警”:车辆 T-Box 注册遗嘱 {"online":false} 到 vehicle/{vin}/status,一旦网络中断,平台立即收到离线通知。若客户端正常发送 DISCONNECT,遗嘱不会发布。
五、综合案例:一次车辆上线到离线的完整链路
假设车辆 T-Box 启动,Client ID 为 TBOX_京A12345,Clean Session=0,Keep Alive=60s,遗嘱主题 vehicle/京A12345/status,遗嘱内容 {"online":false},Will Retain=true。连接成功后,T-Box 向 vehicle/京A12345/status 发布 {"online":true} 并设置 retain=true。平台订阅 vehicle/+/status,立即收到该车在线状态。随后 T-Box 以 QoS 1 上报 vehicle/京A12345/telemetry/speed,平台以 QoS 1 订阅并逐条 PUBACK。若车辆驶入隧道断网,Keep Alive 超时后 Broker 发布遗嘱,平台收到 {"online":false},触发离线告警。车辆重新入网后,因 Clean Session=0,会话恢复,继续上报。
六、排障与复盘要点
- 连接失败:先查 Client ID 是否重复、用户名密码是否正确、Keep Alive 是否过短导致频繁掉线。
- 消息收不到:检查主题层级是否一致、通配符位置是否正确、发布与订阅 QoS 是否匹配。
- 消息重复:QoS 1 允许重复,业务侧需用消息 ID 或时间戳做幂等处理。
- 离线未告警:确认遗嘱是否注册、Will Retain 是否设置、客户端是否正常发送了 DISCONNECT。
- 状态不同步:检查保留消息是否被后续空 payload 清除,或新订阅者是否在发布前已订阅。