反馈

MQTT 深度解析:协议架构、报文、QOS、安全

MQTT(Message Queuing Telemetry Transport)是一种轻量级、发布/订阅(Pub/Sub)模式的消息传输协议,广泛应用于物联网(IoT)、实时设备通信、传感器数据上传、智能家居等场景。由于其开销小、带宽需求低、实现简单,MQTT 已成为物联网领域最主流的通信协议之一。

本文将从协议层面深入解析 MQTT 的基础概念、报文结构、流控机制、QoS 实现、会话持久化、性能优化以及与 MQTT 5.0 的差异,帮助开发者深入理解 MQTT 的底层原理。


1. MQTT 是什么?

MQTT需求

MQTT 最早由 IBM 的 Andy Stanford-Clark 博士和 Arlen Nipper 在 1999 年发明,最初是为了通过卫星网络监控石油管道而设计的。当时的需求是:

因此 MQTT 被设计得极度轻量、可靠、可靠,协议头部最小只有 2 字节。

2014 年,MQTT 成为 OASIS 开放标准,目前最新版本是 MQTT 5.0(2019 年发布),旧版本 MQTT 3.1.1 仍然被广泛使用。

MQTT设计目标

MQTT 最初的设计目标是:

MQTT设计理念

其核心设计理念如下:

轻量、低开销

MQTT 控制报文头部仅有 2 字节起步:

相比 HTTP 动辄上百字节的头部,MQTT 极为轻量。


发布订阅(Pub/Sub)架构

与传统的客户端-服务器(Client/Server)模式不同,MQTT 使用发布-订阅模式,彻底解耦了消息的生产者和消费者。具体特点如下:


长连接 + 保活机制

通过 TCP 长连接减少握手开销,并使用 Keep Alive 保持连接存活。


多级 QoS 保证消息可靠性

允许通过不同 QoS 与网络环境匹配,从弱实时到强一致的消息传输场景全覆盖。

MQTT和其他协议对比

协议 特点 适用场景
MQTT 轻量、Pub/Sub、基于 TCP 物联网、工控系统、智能家居、Web与APP及时通信
HTTP 请求响应、开销大 Web、API
WebSocket 全双工、无 QoS 聊天推送
CoAP 类似 UDP、轻量 受限设备(更轻 than MQTT)
AMQP 企业级消息总线 金融、企业中间件

MQTT 在 设备侧通信领域独占鳌头。


2. 核心组件与消息模型

MQTT 的运作依赖三个核心角色:消息代理服务器、发布者、订阅者,这三者通过主题来交互信息。

2.1 Broker(消息代理服务器)

Broker 提供安全、存储、会话管理、主题路由等功能。


2.2 Publisher(发布者)

向某一个主题(Topic)发送消息的客户端。例如:

Topic: sensors/temperature
Payload: 23.7

2.3 Subscriber(订阅者)

订阅某个主题,接收所有来自 Broker 转发的消息。一个设备既可以是发布者,也可以是订阅者,甚至两者同时是。


2.4 Topic(主题)

MQTT 使用“主题”来标识消息的类别,类似于文件系统的路径。

格式:层级结构,用 / 分隔,例如:

home/livingroom/temperature
device/123/status
sensor/+/humidity

2.5 通配符

MQTT 提供两种通配符,用于批量订阅:

通配符 含义
+ 单级通配符(匹配一个主题层级)
# 多级通配符(匹配任意数量层级)

例子:

home/+/temperature   # 匹配 home/room1/temperature
home/#               # 匹配 home 下所有内容

Topic 匹配由 Broker 进行树结构路由,通常采用**前缀树(Trie)**实现。

3. MQTT 报文

报文类型

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. 固定头(Fixed Header)

固定头第 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

2. 可变头(Variable Header)

各报文不同。典型例子如 PUBLISH:

Topic Name Length
Topic Name
Packet Identifier(QoS > 0 必有)

3. 消息体(Payload)

根据报文类型不同:


4. QoS(消息质量等级)底层实现机制

MQTT 提供三种 QoS:

QoS 0:最多一次


QoS 1:至少一次(At Least Once)

这是一个简单的“请求-确认”机制。

  1. Client: 发送 PUBLISH (带 Packet ID = X)。
    • 客户端此时会保存消息,直到收到确认为止。
  2. Broker: 收到消息,处理(或转发),然后回复 PUBACK (Packet ID = X)。
  3. Client: 收到 PUBACK,删除本地缓存的消息。
    • 风险: 如果 PUBACK 丢包,客户端会重发 PUBLISH,导致 Broker 收到重复消息。
Client → PUBLISH → Broker
Broker → PUBACK

如果 ACK 丢失,客户端重发 PUBLISH(DUP=1)。

可能导致重复消息,业务层需幂等。


QoS 2:恰好一次(Exactly Once)

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) 确保仅一次,不重复 金融交易、计费等必须严格一次

5. 会话、保活与遗嘱消息

MQTT 的强大之处在于处理“连接断开”的能力。这主要通过 Session(会话) 机制控制。

会话与持久会话(Clean Session / Clean Start)

持久会话可用于:


客户端标识:Client ID


Keep Alive(保活机制)

MQTT 使用心跳(PINGREQ/PINGRESP)维持 TCP 连接,检测设备是否离线。

遗嘱消息(Last Will Message)

客户端在连接时可以设置一条“遗嘱消息”。如果客户端异常掉线(没有正常发送 DISCONNECT),Broker 会自动发布这遗嘱消息。常用于监控设备是否在线,例如:

Topic: home/device/123/status
payload: offline
retain: true

这对于 设备在线状态、故障检测、即时告警系统 非常关键。

保留消息(Retained Message)

发布者可以在发布消息时设置 Retained = true,Broker 会保存该主题的最后一条消息。新订阅者订阅该主题时,会立刻收到这条保留消息。常用于上报设备当前状态(如温度、开关状态等)。

例如:

Topic: light/1/status
Message: on (retain)

新订阅者立刻收到“on”。


6. MQTT 的流控与重传机制

重传机制

消息队列

Broker 会为每个 Client 保存:

队列增长过大会导致:

生产中需配置:


7. 性能:百万级连接的实现基础

优秀的 Broker(如 EMQX、Mosquitto)可以支持百万级连接,其依据包括:

基于事件驱动(Epoll/Kqueue)网络模型

避免阻塞式 IO 造成线程爆炸。


主题树(Trie)高效匹配

支持百万级 Topic 订阅


零拷贝数据传输

使用 sendfile、mmap 等技术减少 CPU 负载。


集群水平扩展

Broker 节点之间支持:


8. MQTT 安全机制深度解析

TLS 加密传输

MQTT 使用 TCP,可直接套 TLS:


身份认证

常见:

ACL 支持细粒度权限:

user device-001
topic read sensors/device-001/#
topic write cmd/device-001/#

防 DDOS 与限流

Broker 通常支持:


9. MQTT 的版本

1. MQTT 3.1(2010)

发布者:IBM + Eurotech 标志:协议开始标准化

这是 MQTT 最早被公开的版本。当时主要用于:

主要特性

不足

3.1 是 MQTT 扩张的开端,但缺乏严格标准。


2. MQTT 3.1.1(2014)

MQTT3.1.1 的发布者是OASIS,目前已经正式成为国际标准。3.1.1 是目前 应用最广、最稳定、兼容性最强 的 MQTT 版本。 多数工业设备、MQTT Broker(如 Mosquitto、EMQX、HiveMQ)都默认支持此版本。

核心改进:

  1. Fix 了大量 3.1 的兼容性问题
  1. 更严格的 Topic 规则
  1. UTF-8 校验更严格

  2. 协议交互变得更可预测

如今大多数 IoT 产品仍以 3.1.1 为基础。


3. MQTT 5.0(2019)

MQTT 5.0 是协议的第二次飞跃,功能更强,更适合云平台、大型物联网平台、分布式系统。5.0 不是对 3.1.1 的补丁,而是 再设计 + 扩展


3.1 MQTT 5.0 的核心增强

① 更丰富的 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:

“我吃不消了,不要发太快。”


3.2 其他改进

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,摆脱明文密码

4. MQTT 5.1(最新草案 / 部分实现中)

状态:OASIS 工作草案(Working Draft) 特性:5.0 的增强,兼容 5.0

5.1 专注于:

当前仍处于草案阶段,未被大规模实现。


5. MQTT-SN(MQTT for Sensor Networks)

适用于:无 TCP 的低功耗无线网络(如 Zigbee、NRF、6LoWPAN)

MQTT-SN 不是“新版本”,而是 MQTT 面向超低功耗网络的变种

5.1 核心特点
5.2 MQTT-SN 明显区别于 MQTT 3.x/5.0
特性 MQTT MQTT-SN
传输层 TCP / WebSocket UDP / ZigBee / BLE
Topic UTF-8 字符串 数值 Topic ID
适用设备 普通 IoT 设备 超低功耗传感器
Broker MQTT Broker SN Gateway(中间层)

6. MQTT 各版本对比总结

下面用一张表总结所有版本的核心特性:

版本 年份 核心特性 使用场景
MQTT 3.1 2010 最初公开版本 内部项目、老旧设备
MQTT 3.1.1 2014 标准化、兼容性强、最广泛使用 工业设备、消费级 IoT
MQTT 5.0 2019 大规模集群、错误码、属性、流控、共享订阅 云平台、企业 IoT、大型系统
MQTT 5.1 (草案) 进一步增强安全与集群能力 未来标准
MQTT-SN 独立规范 面向 UDP、超低功耗网络 传感器网络、BLE、Zigbee

7. 该选择哪种版本?

如果你在做消费级 IoT、工业 IoT、智能家居

✔ 使用 MQTT 3.1.1(兼容强、设备支持广)

如果你在做云平台、百万设备级 IoT、服务器侧系统

✔ 使用 MQTT 5.0(更现代、更易运维)

如果你做的是传感器网络、无 TCP 的无线协议

✔ 使用 MQTT-SN

如果你需要提前适配未来标准

✔ 可关注 MQTT 5.1 草案

MQTT 5 对协议进行了重要升级,

10. 常见工具库、客户端和Broker

工具库

常见工具库如下:

语言 推荐库
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

主流开源 MQTT Broker

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

云 MQTT Broker

云平台 性能与扩展 支持协议 特点 适用场景
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 开发常用

11. 总结

MQTT 之所以成为物联网的核心协议,是因为它在轻量性、可靠性、可扩展性和安全性之间做到了完美平衡。MQTT也存在一些限制,如:需要稳定的 TCP 连接(不适合极端弱网)、需要建 Broker,不像 REST 那样简单、不适合大文件传输。

MQTT 已经不再是“物联网协议”,而是现代分布式系统中“最轻量、最可靠、最通用”的消息总线。 只要你有设备、有网络波动、有低功耗需求、有海量连接需求,MQTT 几乎永远是正确答案。