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 / PUBCOMPOTA 结果、计费凭证

注意: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,会话恢复,继续上报。

MQTT 核心机制综合链路 车辆 T-Box Client ID: TBOX_京A12345 Clean Session = 0 Keep Alive = 60s Will: online=false Will Retain = true MQTT Broker 会话保持 / 主题路由 QoS 协商与确认 保留消息存储 遗嘱消息触发 通配符匹配 车联网平台 订阅 vehicle/+/status 订阅 telemetry/speed QoS 1 接收 离线告警 状态展示 CONNECT CONNACK SUBSCRIBE PUBLISH 主题与通配符 vehicle/京A12345/telemetry/speed vehicle/+/telemetry/speed → 匹配任意车辆 vehicle/京A12345/# → 匹配该车全部子主题 避免使用 # 订阅全量主题 QoS 0 / 1 / 2 0:最多一次,高频遥测 1:至少一次,控车指令 2:恰好一次,计费凭证 保留消息 retain=true 保存最后一条 新订阅立即收到最新状态 适合车辆在线状态 遗嘱消息 异常断开时由 Broker 发布 正常 DISCONNECT 不触发 适合离线告警

六、排障与复盘要点

  • 连接失败:先查 Client ID 是否重复、用户名密码是否正确、Keep Alive 是否过短导致频繁掉线。
  • 消息收不到:检查主题层级是否一致、通配符位置是否正确、发布与订阅 QoS 是否匹配。
  • 消息重复:QoS 1 允许重复,业务侧需用消息 ID 或时间戳做幂等处理。
  • 离线未告警:确认遗嘱是否注册、Will Retain 是否设置、客户端是否正常发送了 DISCONNECT。
  • 状态不同步:检查保留消息是否被后续空 payload 清除,或新订阅者是否在发布前已订阅。
掌握这五项机制后,MQTT 在车联网中的行为就不再是“黑盒”:连接决定会话是否延续,主题决定消息去哪,QoS 决定消息多可靠,保留消息决定新订阅者能否立即拿到状态,遗嘱消息决定异常离线能否被及时发现。工程落地时,建议把这几项参数写入车辆接入规范,并在联调阶段逐项验证。