MQTT基础概念:发布/订阅模型、主题、服务质量、会话与遗嘱消息
MQTT 之所以能成为物联网场景中使用最广泛的协议之一,核心在于它并非传统的“客户端直连客户端”通信模式,而是引入了一个消息代理(Broker)作为中枢。所有客户端都不直接知道对方的存在,只与 Broker 打交道。这种架构带来了极强的解耦性:发送者不需要关心接收者是否在线,接收者也不需要关心发送者的地址。理解这一模型,是掌握 MQTT 报文结构的前提——因为后续所有报文类型,本质上都是在为这个模型服务。
2.1 发布/订阅模型:消息的“中间人”机制
在发布/订阅模型中,通信双方被划分为发布者(Publisher)与订阅者(Subscriber)。发布者将消息发送到一个“主题”上,订阅者则表达对某个主题的兴趣。Broker 负责接收发布者的消息,并根据订阅关系将消息转发给所有匹配的订阅者。关键特性如下:
- 空间解耦:发布者与订阅者不需要知道对方的网络地址或身份。
- 时间解耦:订阅者离线时,发布者依然可以发布消息(配合持久会话可离线接收)。
- 同步解耦:发布/订阅操作均为异步,发布者无需阻塞等待订阅者确认。
下图展示了 MQTT 发布/订阅模型的核心交互流程,以及 Broker 在其中的路由作用:
2.2 主题(Topic):消息的“地址”
主题是 MQTT 消息路由的依据,采用UTF-8 字符串表示,以正斜杠 / 作为层级分隔符。主题不需要提前创建,发布者直接向某个主题发布消息,Broker 即自动建立该主题的路由。主题设计直接影响系统的可扩展性与安全性。
主题支持两种通配符,用于订阅时的模糊匹配:
| 通配符 | 名称 | 匹配规则 | 示例 |
|---|---|---|---|
+ |
单层通配符 | 匹配一个层级 | sensor/+/temp 匹配 sensor/room1/temp |
# |
多层通配符 | 匹配剩余所有层级,必须位于末尾 | sensor/# 匹配 sensor/room1/temp 和 sensor/room2/humidity |
/ 开头或结尾(如 /sensor/temp/),不要包含空格或非 ASCII 字符,不要使用 # 或 + 作为主题的实际内容(它们是保留字符)。主题层级不宜过深(建议不超过 5 层),否则会降低 Broker 路由效率。
2.3 服务质量(QoS):消息送达的三种保障等级
MQTT 提供三个 QoS 等级,用于控制消息在发布者与订阅者之间的投递保障。等级越高,可靠性越强,但网络开销也越大。QoS 是 MQTT 报文头中一个关键字段(占 2 bit),其取值决定了后续报文交互流程。
- QoS 0(至多一次):消息尽力发送,不确认、不重发。适用于传感器高频数据(如每 5 秒上报一次温度),丢失一帧影响不大。
- QoS 1(至少一次):发送后等待
PUBACK确认,超时未收到则重发。接收方可能收到重复消息,需应用层去重。 - QoS 2(恰好一次):通过四步握手(
PUBLISH → PUBREC → PUBREL → PUBCOMP)确保消息不重不漏。适用于计费指令、设备控制等关键场景。
QoS 的协商机制值得注意:发布者的 QoS 与订阅者的 QoS 取最小值作为实际投递等级。例如发布者发送 QoS 1 消息,但订阅者订阅时申请 QoS 0,则 Broker 以 QoS 0 转发。
2.4 会话(Session):连接的状态记忆
MQTT 会话是客户端与 Broker 之间的一种逻辑状态关联,由 CONNECT 报文中的 Clean Start 标志位决定。会话分为两种:
- 持久会话(Clean Start = 0):Broker 保存客户端的订阅关系、离线期间未投递的 QoS 1/2 消息。客户端重新连接后,无需重新订阅即可接收离线消息。
- 临时会话(Clean Start = 1):连接断开即销毁所有会话状态,重新连接后必须重新订阅。
会话还包含一个 Session Expiry Interval 参数(在 CONNECT 报文中),表示会话在连接断开后保留的秒数。若设为 0,则连接断开即结束会话;若设为 0xFFFFFFFF,则永久保留。
2.5 遗嘱消息(Will Message):异常离线的“最后遗言”
遗嘱消息是 MQTT 为物联网场景设计的独特机制。客户端在建立连接时,可在 CONNECT 报文中携带遗嘱主题、遗嘱消息内容及遗嘱 QoS。当发生以下情况时,Broker 会代替该客户端发布遗嘱消息:
- 网络连接异常断开(如 TCP 超时、心跳超时),且未收到
DISCONNECT报文。 - Broker 检测到协议错误,主动关闭连接。
如果客户端正常发送 DISCONNECT 报文后断开,Broker 会丢弃遗嘱消息,不会发布。遗嘱消息常用于设备状态监控——例如智能门锁异常掉线时,向 device/status 主题发布 offline 消息,让监控平台及时感知。
2.6 综合案例:智能家居温度监控系统
假设一个智能家居系统包含温度传感器、手机 App 和云端数据库。传感器每 10 秒上报一次温度,App 需要实时显示,云端需要持久化存储。系统设计如下:
传感器(发布者):
- 连接参数: Broker地址 tcp://192.168.1.100:1883
- Clean Start = 0(持久会话)
- Will Topic: device/sensor01/status
- Will Message: "offline" (QoS 1)
- 发布主题: sensor/room1/temp
- 发布 QoS: 1
手机 App(订阅者):
- 订阅主题: sensor/room1/temp
- 订阅 QoS: 0(实时刷新,允许偶尔丢帧)
- Clean Start = 0
云端数据库(订阅者):
- 订阅主题: sensor/room1/temp
- 订阅 QoS: 1(需要完整数据,允许重复但不可丢失)
- Clean Start = 0
当传感器因断电突然离线时,Broker 检测到 TCP 连接超时,立即向 device/sensor01/status 主题发布遗嘱消息 "offline"。监控平台(已订阅该主题)收到消息后触发告警。传感器恢复后重新连接,由于使用持久会话,Broker 将离线期间缓存的 QoS 1 温度数据推送给云端数据库,保证数据完整性。
2.7 常见误区与设计复盘
复盘整个设计,MQTT 的这五个基础概念并非孤立存在,而是相互关联:主题定义了消息的“路径”,发布/订阅模型决定了消息的“流向”,QoS 控制消息的“可靠性”,会话管理消息的“状态记忆”,遗嘱消息则处理异常场景的“最后通知”。理解这些概念后,再去看 MQTT 控制报文的二进制结构,就能明白每个字段为何存在、如何协作。