MQTT(Message Queuing Telemetry Transport)是一种轻量级、发布/订阅(Pub/Sub)模式的消息传输协议,广泛应用于物联网(IoT)、实时设备通信、传感器数据上传、智能家居等场景。由于其开销小、带宽需求低、实现简单,MQTT 已成为物联网领域最主流的通信协议之一。
本文将从协议层面深入解析 MQTT 的基础概念、报文结构、流控机制、QoS 实现、会话持久化、性能优化以及与 MQTT 5.0 的差异,帮助开发者深入理解 MQTT 的底层原理。
MQTT 最早由 IBM 的 Andy Stanford-Clark 博士和 Arlen Nipper 在 1999 年发明,最初是为了通过卫星网络监控石油管道而设计的。当时的需求是:
因此 MQTT 被设计得极度轻量、可靠、可靠,协议头部最小只有 2 字节。
2014 年,MQTT 成为 OASIS 开放标准,目前最新版本是 MQTT 5.0(2019 年发布),旧版本 MQTT 3.1.1 仍然被广泛使用。
MQTT 最初的设计目标是:
其核心设计理念如下:
MQTT 控制报文头部仅有 2 字节起步:
相比 HTTP 动辄上百字节的头部,MQTT 极为轻量。
与传统的客户端-服务器(Client/Server)模式不同,MQTT 使用发布-订阅模式,彻底解耦了消息的生产者和消费者。具体特点如下:
通过 TCP 长连接减少握手开销,并使用 Keep Alive 保持连接存活。
允许通过不同 QoS 与网络环境匹配,从弱实时到强一致的消息传输场景全覆盖。
| 协议 | 特点 | 适用场景 |
|---|---|---|
| MQTT | 轻量、Pub/Sub、基于 TCP | 物联网、工控系统、智能家居、Web与APP及时通信 |
| HTTP | 请求响应、开销大 | Web、API |
| WebSocket | 全双工、无 QoS | 聊天推送 |
| CoAP | 类似 UDP、轻量 | 受限设备(更轻 than MQTT) |
| AMQP | 企业级消息总线 | 金融、企业中间件 |
MQTT 在 设备侧通信领域独占鳌头。
MQTT 的运作依赖三个核心角色:消息代理服务器、发布者、订阅者,这三者通过主题来交互信息。
Broker 是 MQTT 的核心,负责:
Broker 提供安全、存储、会话管理、主题路由等功能。
向某一个主题(Topic)发送消息的客户端。例如:
Topic: sensors/temperature
Payload: 23.7
订阅某个主题,接收所有来自 Broker 转发的消息。一个设备既可以是发布者,也可以是订阅者,甚至两者同时是。
MQTT 使用“主题”来标识消息的类别,类似于文件系统的路径。
格式:层级结构,用 / 分隔,例如:
home/livingroom/temperature
device/123/status
sensor/+/humidity
MQTT 提供两种通配符,用于批量订阅:
| 通配符 | 含义 |
|---|---|
+ |
单级通配符(匹配一个主题层级) |
# |
多级通配符(匹配任意数量层级) |
例子:
home/+/temperature # 匹配 home/room1/temperature
home/# # 匹配 home 下所有内容
Topic 匹配由 Broker 进行树结构路由,通常采用**前缀树(Trie)**实现。
MQTT 共定义 14 种控制报文(Control Packet):
| 报文类型 | 方向 | 描述 |
|---|---|---|
| CONNECT | 客户端→Broker | 客户端请求连接 |
| CONNACK | Broker→客户端 | 连接确认 |
| PUBLISH | 双向 | 发布消息 |
| PUBACK | 双向 | QoS1 发布确认 |
| PUBREC | 双向 | QoS2 流程第一步(已接收) |
| PUBREL | 双向 | QoS2 流程第二步(释放) |
| PUBCOMP | 双向 | QoS2 流程结束(完成) |
| SUBSCRIBE | 客户端→Broker | 订阅请求 |
| SUBACK | Broker→客户端 | 订阅响应 |
| UNSUBSCRIBE | 客户端→Broker | 取消订阅 |
| UNSUBACK | Broker→客户端 | 取消订阅响应 |
| PINGREQ | 客户端→Broker | 心跳请求 |
| PINGRESP | Broker→客户端 | 心跳应答 |
| DISCONNECT | 双向(5.0 更丰富) | 断线 |
每个 MQTT 报文都包含三部分:
[Fixed Header] [Variable Header] [Payload]
固定头第 1 字节:
bit7-4: Control Packet Type
bit3-0: Flags(某些报文固定,某些与 DUP/QoS/RETAIN 相关)
固定头第 2 字节及以后为:
Remaining Length(变长编码)
采用 7-bit 编码 + 1-bit 延续位:
示例:
0x96 0x01
二进制: 1001 0110 0000 0001
值:150
各报文不同。典型例子如 PUBLISH:
Topic Name Length
Topic Name
Packet Identifier(QoS > 0 必有)
根据报文类型不同:
MQTT 提供三种 QoS:
这是一个简单的“请求-确认”机制。
PUBLISH (带 Packet ID = X)。
PUBACK (Packet ID = X)。PUBACK,删除本地缓存的消息。
PUBACK 丢包,客户端会重发 PUBLISH,导致 Broker 收到重复消息。Client → PUBLISH → Broker
Broker → PUBACK
如果 ACK 丢失,客户端重发 PUBLISH(DUP=1)。
可能导致重复消息,业务层需幂等。
MQTT 最复杂的流程,采用 4 次消息握手:
客户端 → Broker : PUBLISH (DUP=0, QoS=2, PacketId=100)
Broker → 客户端 : PUBREC (PacketId=100)
客户端 → Broker : PUBREL (PacketId=100)
Broker → 客户端 : PUBCOMP (PacketId=100)
Broker 和客户端各自维护“QoS 2 进行中消息列表”,必须在收到 PUBCOMP 后才真正删除。保证消息 不丢失、不重复。代价是性能开销大,通常不推荐频繁使用。 QoS 2 虽然完美,但网络交互次数是 QoS 0 的四倍以上。在实战中,许多高吞吐系统倾向于使用 QoS 1,并在业务层(如通过业务 ID)进行去重。
三种等级应用场景如下:
| QoS 等级 | 描述 | 适用场景 |
|---|---|---|
| 0(At most once) | 至多一次,不保证送达 | 传感器频繁上报、丢一点无所谓 |
| 1(At least once) | 至少一次,可能重复 | 业务消息,一次可能重复可接受 |
| 2(Exactly once) | 确保仅一次,不重复 | 金融交易、计费等必须严格一次 |
MQTT 的强大之处在于处理“连接断开”的能力。这主要通过 Session(会话) 机制控制。
MQTT 3.1.1:Clean Session = true → 每次连接都是全新会话,断开后订阅丢失
Clean Session = false → 持久会话,Broker 会保存订阅关系和未送达的 QoS 1/2 消息,下次连接恢复
MQTT 5.0:改为 Clean Start 标志 + Session Expiry Interval,更灵活
持久会话可用于:
MQTT 使用心跳(PINGREQ/PINGRESP)维持 TCP 连接,检测设备是否离线。
客户端在连接时可以设置一条“遗嘱消息”。如果客户端异常掉线(没有正常发送 DISCONNECT),Broker 会自动发布这遗嘱消息。常用于监控设备是否在线,例如:
Topic: home/device/123/status
payload: offline
retain: true
这对于 设备在线状态、故障检测、即时告警系统 非常关键。
发布者可以在发布消息时设置 Retained = true,Broker 会保存该主题的最后一条消息。新订阅者订阅该主题时,会立刻收到这条保留消息。常用于上报设备当前状态(如温度、开关状态等)。
例如:
Topic: light/1/status
Message: on (retain)
新订阅者立刻收到“on”。
Broker 会为每个 Client 保存:
队列增长过大会导致:
生产中需配置:
优秀的 Broker(如 EMQX、Mosquitto)可以支持百万级连接,其依据包括:
避免阻塞式 IO 造成线程爆炸。
支持百万级 Topic 订阅
使用 sendfile、mmap 等技术减少 CPU 负载。
Broker 节点之间支持:
MQTT 使用 TCP,可直接套 TLS:
常见:
ACL 支持细粒度权限:
user device-001
topic read sensors/device-001/#
topic write cmd/device-001/#
Broker 通常支持:
发布者:IBM + Eurotech 标志:协议开始标准化
这是 MQTT 最早被公开的版本。当时主要用于:
主要特性
不足
3.1 是 MQTT 扩张的开端,但缺乏严格标准。
MQTT3.1.1 的发布者是OASIS,目前已经正式成为国际标准。3.1.1 是目前 应用最广、最稳定、兼容性最强 的 MQTT 版本。 多数工业设备、MQTT Broker(如 Mosquitto、EMQX、HiveMQ)都默认支持此版本。
核心改进:
$ 开头的 Topic 被普通客户端发布UTF-8 校验更严格
协议交互变得更可预测
如今大多数 IoT 产品仍以 3.1.1 为基础。
MQTT 5.0 是协议的第二次飞跃,功能更强,更适合云平台、大型物联网平台、分布式系统。5.0 不是对 3.1.1 的补丁,而是 再设计 + 扩展。
① 更丰富的 Reason Code(错误码)
MQTT 3.1.1 错误反馈极其有限,5.0 改进如下:
② 用户属性(User Properties)
每条消息都可带键值对:
User-Property: source = camera1
User-Property: building = A1
用于:
③ 共享订阅(Shared Subscriptions)
解决消费者负载均衡问题:
$share/group1/sensors/#
等效于:
④ 会话过期(Session Expiry)
替代 3.1.1 的 Clean Session Boolean:
⑤ 流控(Flow Control)
客户端可告诉 Broker:
“我吃不消了,不要发太快。”
5.0 是“大型云平台与大型 IoT 系统研发的首选”。
关键特性包括:
| 特性 | 实际价值 |
|---|---|
| 原因码(Reason Code) | 每个响应包都有 8bit 原因码,错误定位从“猜”变成“精确” |
| 用户属性(User Properties) | 类似 HTTP Header,可传 traceId、tenantId、version 等,调试神器 |
| 会话过期时间(Session Expiry Interval) | 精确控制离线消息保存时长,解决 3.1.1 “永久保存”导致内存爆炸问题 |
| 消息过期时间(Message Expiry Interval) | 发布时可设置消息 TTL,适合遥测数据 |
| 主题别名(Topic Alias) | 客户端与 Broker 协商别名后,后续只发 alias id,可省 90% 以上主题字节 |
| 请求/响应模式(Response Topic + Correlation Data) | 原生支持 RPC 风格通信,不再需要“黑魔法”回复主题 |
| 最大包大小(Maximum Packet Size) | 客户端可声明自己能接受的最大包,防止 Broker 发超大包导致断连 |
| 增强认证(Enhanced Authentication) | 支持 SCRAM、Challenge-Response,摆脱明文密码 |
状态:OASIS 工作草案(Working Draft) 特性:5.0 的增强,兼容 5.0
5.1 专注于:
当前仍处于草案阶段,未被大规模实现。
适用于:无 TCP 的低功耗无线网络(如 Zigbee、NRF、6LoWPAN)
MQTT-SN 不是“新版本”,而是 MQTT 面向超低功耗网络的变种。
| 特性 | MQTT | MQTT-SN |
|---|---|---|
| 传输层 | TCP / WebSocket | UDP / ZigBee / BLE |
| Topic | UTF-8 字符串 | 数值 Topic ID |
| 适用设备 | 普通 IoT 设备 | 超低功耗传感器 |
| Broker | MQTT Broker | SN Gateway(中间层) |
下面用一张表总结所有版本的核心特性:
| 版本 | 年份 | 核心特性 | 使用场景 |
|---|---|---|---|
| MQTT 3.1 | 2010 | 最初公开版本 | 内部项目、老旧设备 |
| MQTT 3.1.1 | 2014 | 标准化、兼容性强、最广泛使用 | 工业设备、消费级 IoT |
| MQTT 5.0 | 2019 | 大规模集群、错误码、属性、流控、共享订阅 | 云平台、企业 IoT、大型系统 |
| MQTT 5.1 | (草案) | 进一步增强安全与集群能力 | 未来标准 |
| MQTT-SN | 独立规范 | 面向 UDP、超低功耗网络 | 传感器网络、BLE、Zigbee |
如果你在做消费级 IoT、工业 IoT、智能家居
✔ 使用 MQTT 3.1.1(兼容强、设备支持广)
如果你在做云平台、百万设备级 IoT、服务器侧系统
✔ 使用 MQTT 5.0(更现代、更易运维)
如果你做的是传感器网络、无 TCP 的无线协议
✔ 使用 MQTT-SN
如果你需要提前适配未来标准
✔ 可关注 MQTT 5.1 草案
MQTT 5 对协议进行了重要升级,
常见工具库如下:
| 语言 | 推荐库 |
|---|---|
| C | Mosquitto lib、Paho C |
| Python | Paho-MQTT、gmqtt |
| Java | Paho Java、HiveMQ Client |
| JavaScript | MQTT.js(浏览器和 Node.js 都支持) |
| Go | Paho Go、EMQX 的 go-mqtt |
| Android | Paho Android Service |
| iOS | CocoaMQTT、Moscow |
| Broker | 开源协议 | 支持版本 | 性能(连接数) | 集群 | 插件生态 | 特点解析 | 适用场景 |
|---|---|---|---|---|---|---|---|
| EMQX | Apache 2.0 | MQTT 3.1.1 / 5.0 | 100万+ | ✔(强) | 强大(Lua / Hooks / Webhook) | 高性能、高扩展性、企业级特性丰富 | 大规模 IoT、企业系统、云平台 |
| Mosquitto | EPL/EDL | MQTT 3.1 / 3.1.1 / 5.0 | ~10万(单节点) | ✖ | 弱 | 最轻量、最稳定、资源占用极少 | 嵌入式、边缘设备、小型部署 |
| HiveMQ Community | Apache 2.0 | MQTT 3.1.1 / 5.0 | ~30万 | ✖(商业版支持) | 一般 | 更偏云、高可靠,商业版强 | 微服务、企业应用、云产品原型 |
| VerneMQ | Apache 2.0 | MQTT 3.1.1 | 50万+ | ✔ | 中 | Erlang 实现,集群可靠 | 分布式系统、工业 IoT |
| RabbitMQ(MQTT 插件) | MPL | MQTT 3.1.1(部分) | 10万+ | ✔ | 超强 | 实际是 AMQP Broker,但支持 MQTT | 企业集成、异构系统 |
| NanoMQ(emqx-lite) | MIT | MQTT 3.1.1 / 5.0 | ~数万 | ✖ | 少 | 超轻量 C 语言 Broker | 边缘网关、嵌入式 Linux |
| 云平台 | 性能与扩展 | 支持协议 | 特点 | 适用场景 |
|---|---|---|---|---|
| EMQX Cloud | 高(全球集群) | MQTT、MQTT over WS、CoAP、LwM2M | 专业 IoT 云、功能最完整 | 企业 IoT、跨国设备 |
| HiveMQ Cloud | 中–高 | MQTT / WebSocket | 更偏企业 SaaS,监控完善 | SaaS 产品、IoT 平台 |
| AWS IoT Core | 高 | MQTT / HTTP / WebSocket | 深度集成 AWS 生态、安全性强 | 云原生团队、AWS 用户 |
| Azure IoT Hub | 高 | MQTT / AMQP / HTTPS | 规则引擎强大,适合工业 | 工业 IoT、企业云上架构 |
| 阿里云 IoT 平台 | 高 | MQTT / CoAP / LwM2M | 国内最成熟 IoT 云 | 中国市场产品 |
| 腾讯云 IoT Explorer | 中 | MQTT | 模块化场景配置强 | 中国消费级 IoT |
| 客户端 | 语言 | 支持协议版本 | QoS | 是否支持 SSL/TLS | 是否支持 WebSocket | 特点与适用场景 |
|---|---|---|---|---|---|---|
| Eclipse Paho | Java / Python / C / C++ / JavaScript / Go | v3.1, v3.1.1, v5 | QoS 0/1/2 | ✓ | ✓ | 最全面的跨语言实现,企业常用;生态成熟,示例丰富 |
| Mosquitto Client (libmosquitto) | C / C++ | v3.1, v3.1.1, v5 | QoS 0/1/2 | ✓ | ✓(需额外支持) | C 语言实现,轻量、高性能,物联网设备常用 |
| HiveMQ MQTT Client | Java | v3.1.1, v5(优秀支持) | QoS 0/1/2 | ✓ | ✓ | 最强 Java MQTT 客户端之一,全面支持 MQTT 5 |
| EMQX MQTT Client(emqtt / NanoSDK) | Erlang / C / C++ / Android | v3.1.1, v5 | QoS 0/1/2 | ✓ | - | 为高性能 IoT 场景优化,并发友好 |
| MQTT.js | Node.js | v3.1, v3.1.1, v5 | QoS 0/1/2 | ✓ | ✓(浏览器) | JavaScript 最强 MQTT 客户端,适合 Web 与 Node 应用 |
| AsyncMQTT / Asyncio-MQTT | Python | v3.1, v3.1.1 | QoS 0/1/2 | ✓ | - | 支持异步 asyncio,适合高并发 I/O 场景 |
| paho-mqtt (Python) | Python | v3.1, v3.1.1, v5 | QoS 0/1/2 | ✓ | 需扩展 | Python 最常用客户端,简单稳定 |
| gmqtt (Python) | Python | v3.1.1, v5 | QoS 0/1/2 | ✓ | ✓ | asyncio,性能不错,优雅支持 MQTT 5 |
| Eclipse Paho Android Service | Android | v3.1.1 | 0/1/2 | ✓ | - | Android 专用,移动端 MQTT 工程常用 |
| rumqtt / rumqttc | Rust | v3.1.1, v5 | QoS 0/1/2 | ✓ | ✓ | Rust 实现,高性能、安全性极高 |
| mqtt_cpp | C++17 | v3.1.1, v5 | 0/1/2 | ✓ | - | header-only,高性能,适合现代 C++ |
| Netty MQTT | Java / Netty | v3.1.1 | 0/1/2 | 可扩展 | - | 用于自定义网关或服务端/客户端开发 |
| Qt MQTT | C++ / Qt | v3.1.1 | ✓ | ✓ | - | Qt 应用程序可直接使用,界面程序常用 |
| SwiftMQTT | Swift / iOS | v3.1.1 | ✓ | ✓ | - | iOS MQTT 开发常用 |
MQTT 之所以成为物联网的核心协议,是因为它在轻量性、可靠性、可扩展性和安全性之间做到了完美平衡。MQTT也存在一些限制,如:需要稳定的 TCP 连接(不适合极端弱网)、需要建 Broker,不像 REST 那样简单、不适合大文件传输。
MQTT 已经不再是“物联网协议”,而是现代分布式系统中“最轻量、最可靠、最通用”的消息总线。 只要你有设备、有网络波动、有低功耗需求、有海量连接需求,MQTT 几乎永远是正确答案。