MQTT 协议原理(符合 MQTT v3.1.1 / v5.0 标准)
本文基于 OASIS 标准 MQTT v3.1.1 和 MQTT v5.0 编写,确保技术准确性。
一、简述
MQTT (Message Queuing Telemetry Transport,消息队列遥测传输协议)是一种基于 客户端-服务器架构 的 发布/订阅 (publish/subscribe) 模式的轻量级通信协议,构建于 TCP/IP 协议栈之上。
MQTT 的最大优点在于:以极少的代码和有限的带宽,为远程设备提供实时、可靠的消息服务 。作为一种低开销、低带宽占用的即时通信协议,它在 物联网(IoT) 等领域得到广泛应用。
二、主要特性
MQTT 协议专为 低带宽、高延迟、不稳定网络环境 下的远程传感器与控制设备通信而设计,具备以下核心特性:
1. 发布/订阅消息模式
- 提供 一对多 的消息分发机制,有效解耦应用程序。
- 相比 XMPP(基于 XML 文本),MQTT 采用 紧凑二进制格式,信息冗余极小。
2. 对负载内容屏蔽
- 协议 不解析 payload 内容,可传输任意数据类型(JSON、二进制、文本等)。
3. 基于 TCP/IP 的可靠连接
- 标准 MQTT 运行在 TCP 之上,确保有序、无损传输。
- MQTT-SN 是面向非 TCP 网络(如 UDP、Zigbee、LoRaWAN)的独立衍生协议,适用于超低功耗设备。
4. 极小传输开销
- 固定头部最小仅 2 字节。
- 协议交互最小化,显著降低网络流量,非常适合资源受限的嵌入式设备。
5. 遗嘱消息机制(Last Will and Testament, LWT)
- 客户端在
CONNECT时可设置一条"遗言"(Will Message)和目标主题。 - 当客户端 异常断开(如掉电、网络中断),Broker 自动将遗言发布到指定主题,通知其他设备该客户端已离线。
三、核心架构与概念
3.1 角色定义
| 角色 | 说明 |
|---|---|
| Client(客户端) | 可作为发布者(Publisher)、订阅者(Subscriber),或两者兼具(如手机 App、传感器)。 |
| Broker(代理服务器) | 消息中枢,负责接收、路由和分发消息(如 Mosquitto、EMQX、HiveMQ)。 |
通信模型:Publisher → Broker → Subscriber
3.2 主题(Topic)
- UTF-8 字符串,用于标识消息类别(如
sensors/room1/temperature)。 - 层级结构,使用
/分隔。 - 支持通配符:
+:单层通配符(匹配一层)#:多层通配符(必须位于末尾)
✅ 示例:
sensors/+/temp匹配sensors/room1/temp,但不匹配sensors/room1/floor2/temp。
3.3 保留消息(Retained Message)
- 发布时设置
RETAIN = 1,Broker 会保存该主题的最后一条消息。 - 新订阅者立即收到该消息,用于同步"当前状态"。
3.4 持久会话(Persistent Session)
- 通过
Clean Start = false(v5.0)或Clean Session = false(v3.1.1)启用。 - Broker 保存:
- 订阅关系
- QoS 1/2 未确认的消息(支持离线缓存)
- 客户端重连后可继续接收错过的消息。
四、服务质量等级(QoS)
MQTT 定义三种 QoS 级别,控制消息传递的可靠性:
QoS 0:至多一次(At Most Once)
✅ 工作原理
- Publisher 直接发送
PUBLISH,不等待确认。 - 完全依赖 TCP 可靠性;若客户端离线,消息永久丢失。
🔍 特点
| 项目 | 说明 |
|---|---|
| 可靠性 | 最低(可能丢失) |
| 重复性 | 不会重复 |
| 延迟 | 最低 |
| 带宽/开销 | 最小(1 条报文) |
| 是否缓存 | 否(离线即丢) |
🎯 典型使用场景
- 高频传感器数据(温度、GPS)
- 实时状态同步(游戏位置、视频流)
- 日志采样(允许少量丢失)
✅ 核心诉求:快、省、可容忍丢失
QoS 1:至少一次(At Least Once)
✅ 工作原理
- Publisher 发送
PUBLISH(含 Packet ID) - Subscriber 回复
PUBACK - 若未收到 ACK,Publisher 重传
- 可能重复接收
⚠️ 应用层需自行去重(如通过消息 ID 或幂等设计)
🔍 特点
| 项目 | 说明 |
|---|---|
| 可靠性 | 高(保证送达) |
| 重复性 | 可能重复 |
| 延迟 | 中等(1 次往返) |
| 带宽/开销 | 中等(2 条报文) |
| 是否缓存 | 是(配合持久会话) |
🎯 典型使用场景
- 移动 APP 推送(订单、聊天)
- 设备控制指令(开关灯、启停电机)
- 告警事件上报
✅ 核心诉求:不能丢,可接受重复(能去重)
QoS 2:恰好一次(Exactly Once)
✅ 工作原理
- 四次握手 确保唯一投递:
PUBLISHPUBRECPUBRELPUBCOMP
- Broker 与客户端协同跟踪状态,杜绝丢失与重复
🔍 特点
| 项目 | 说明 |
|---|---|
| 可靠性 | 最高 |
| 重复性 | 严格不重复 |
| 延迟 | 最高(2 次往返) |
| 带宽/开销 | 最大(4 条报文) |
| 是否缓存 | 是 |
🎯 典型使用场景
- 金融交易(转账、扣款)
- 计费系统
- 关键配置下发(重复会导致故障)
⚠️ 注意 :QoS 2 开销大,在 IoT 场景中极少使用 ;多数业务可通过 QoS 1 + 幂等设计 替代。
✅ 核心诉求:绝对不能丢、也不能重复,且无法在应用层去重
QoS 对比总结表
| 特性 | QoS 0 | QoS 1 | QoS 2 |
|---|---|---|---|
| 别名 | Fire and Forget | Acknowledged Delivery | Assured Delivery |
| 消息是否可能丢失 | ✅ 是 | ❌ 否 | ❌ 否 |
| 消息是否可能重复 | ❌ 否 | ✅ 是 | ❌ 否 |
| 报文数量 | 1 | 2 | 4 |
| 性能开销 | 最低 | 中等 | 最高 |
| 是否适合离线设备 | ❌ 否 | ✅ 是(需持久会话) | ✅ 是 |
| 典型应用 | 传感器数据 | APP 推送、控制指令 | 金融交易、计费 |
五、MQTT 控制报文与数据包结构
5.1 控制报文(Control Packets)
MQTT 定义多种控制报文,常用包括:
CONNECT/CONNACK:建立连接PUBLISH:发布消息SUBSCRIBE/SUBACK:订阅管理UNSUBSCRIBE/UNSUBACK:退订PINGREQ/PINGRESP:心跳保活DISCONNECT:正常断开
5.2 数据包结构
每个 MQTT 报文由三部分组成:
(1)固定头(Fixed Header)
- 所有报文必含。
- 第 1 字节:报文类型 (高 4 位) + 标志位(低 4 位)。
- 后续字节:Remaining Length (剩余长度),使用 可变字节编码(1~4 字节)。
标志位(以 PUBLISH 为例):
| 标志 | 含义 |
|---|---|
| DUP | 重传标志(1=此消息为重发,可用于去重) |
| QoS | 服务质量(00/01/10) |
| RETAIN | 保留标志(1=Broker 保存此消息) |
(2)可变头(Variable Header)
- 部分报文包含(如 CONNECT、PUBLISH)。
- 常见字段:Packet Identifier(2 字节,用于 QoS > 0 的确认机制)。
(3)负载(Payload)
- 存在于以下报文:
CONNECT:Client ID、Will Message、用户名/密码PUBLISH:应用消息内容(用户数据)SUBSCRIBE:主题列表 + QoSUNSUBSCRIBE:主题列表
六、典型工作流程
-
连接
Client →
CONNECT→ Broker →CONNACK→ Client -
订阅
Client →
SUBSCRIBE→ Broker →SUBACK→ Client -
发布
Publisher →
PUBLISH→ Broker →PUBLISH→ Subscriber(根据 QoS 进行确认交互)
-
保活
Client ↔
PINGREQ/PINGRESP↔ Broker(按 Keep Alive 间隔) -
断开
Client →
DISCONNECT→ Broker(可选,用于正常退出)
七、使用建议与最佳实践
- ✅ 优先使用 QoS 1:平衡可靠性与性能,配合应用层去重。
- ✅ 慎用 QoS 2:仅在无法容忍重复且性能允许时使用。
- ✅ 合理使用 Retained Message:用于传递设备最新状态。
- ✅ 启用持久会话(Clean Session = false):确保离线消息不丢失。
- ✅ 设置 LWT:提升系统对设备在线状态的感知能力。
八、一句话选型指南
- 数据丢了也无所谓? → QoS 0
- 消息不能丢,重复我能处理? → QoS 1
- 丢了不行,重复也不行,且我愿意付出性能代价? → QoS 2
📌 适用场景 :物联网设备通信、移动推送、工业监控、车联网、智能家居等。
📚 标准依据:OASIS MQTT v3.1.1 / v5.0(ISO/IEC 20922)