2. 物联网与MQTT基础
2.1 物联网分层架构与通信定位
物联网系统通常采用分层架构设计,每一层承担不同的职责。理解分层有助于我们判断 MQTT 在整体系统中处于哪一环节,以及它解决了什么问题。
| 层次 | 典型组件 | 主要职责 | 常用协议 |
|---|---|---|---|
| 感知层 | 温湿度传感器、GPS 模块、智能电表 | 数据采集与物理信号数字化 | I2C、SPI、Modbus |
| 网络层 | Wi-Fi 模组、4G/5G 模块、LoRa 网关 | 接入互联网、数据透传 | TCP/IP、UDP、LoRaWAN |
| 平台层 | 云服务器、消息中间件、数据库 | 设备管理、消息路由、数据存储 | MQTT、AMQP、HTTP |
| 应用层 | 手机 App、Web 仪表盘、告警系统 | 数据可视化、业务逻辑、用户交互 | HTTPS、WebSocket |
MQTT 位于网络层与平台层之间,它运行在 TCP 之上,为设备与云平台之间提供轻量级、可靠的消息通道。在典型的物联网公有云接入场景中,设备端通过 MQTT 客户端连接到云平台(如阿里云 IoT、AWS IoT Core),将采集到的数据发布到指定主题,云平台再转发给订阅了该主题的应用服务。
2.2 MQTT 协议概述与设计目标
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)由 IBM 于 1999 年提出,2014 年成为 OASIS 标准。它专为低带宽、高延迟、网络不稳定的远程连接场景设计,核心设计目标包括:
- 极简协议头:固定报文头仅 2 字节,最小消息开销远低于 HTTP 的数百字节。
- 异步解耦:发布者与订阅者互不感知对方存在,通过 Broker 中转。
- 可靠投递:提供 QoS 0/1/2 三级服务质量,适应不同业务需求。
- 会话保持:支持持久会话,设备断线重连后不丢失离线消息。
- 遗嘱机制:设备异常离线时,Broker 可代为发布遗嘱消息,通知其他订阅者。
MQTT 协议报文由三部分组成:固定报头(所有报文必备)、可变报头(部分报文需要)、有效载荷(消息内容)。其中固定报头第一个字节的高 4 位表示报文类型,例如 3 代表 PUBLISH(发布消息),8 代表 SUBSCRIBE(订阅请求),14 代表 DISCONNECT(断开连接)。
MQTT 报文结构示例(PUBLISH 消息):
+----------------+----------------+----------------+----------------+
| 固定报头 Byte1 | 固定报头 Byte2 | 可变报头(主题) | 有效载荷(数据) |
| 0x30 (PUBLISH)| 剩余长度 | "dev/001/temp" | "25.6" |
+----------------+----------------+----------------+----------------+
2.3 发布/订阅模型与 Broker 角色
MQTT 采用发布/订阅(Pub/Sub)模型,消息的发送方(Publisher)与接收方(Subscriber)完全解耦。它们之间通过一个中心节点——Broker(消息代理)——进行消息路由。
发布/订阅模型的核心价值在于:
- 空间解耦:发布者不需要知道订阅者的 IP 地址或端口。
- 时间解耦:订阅者离线时,Broker 可暂存消息(需持久会话支持),上线后补发。
- 同步解耦:发布者发布消息后立即返回,无需等待订阅者处理完成。
Broker 的职责包括:维护客户端连接、处理订阅关系、匹配主题并转发消息、管理会话状态、执行 QoS 策略。常见的公有云 Broker 有 EMQX Cloud、阿里云微消息队列 MQTT 版、AWS IoT Core 等。
2.4 主题(Topic)与通配符(Wildcard)
主题是 MQTT 消息路由的核心寻址机制。它采用 UTF-8 字符串,以正斜杠 / 作为层级分隔符,例如:
设备数据上报: /devices/{deviceId}/telemetry
设备状态变更: /devices/{deviceId}/status
云端指令下发: /devices/{deviceId}/command
告警通知: /alerts/{deviceId}/warning
主题的层级结构允许使用通配符进行灵活订阅。MQTT 提供两种通配符:
| 通配符 | 含义 | 示例 | 匹配结果 |
|---|---|---|---|
+ |
单层匹配 | /devices/+/telemetry |
匹配 /devices/001/telemetry、/devices/002/telemetry,但不匹配 /devices/001/status |
# |
多层匹配(必须位于末尾) | /devices/# |
匹配 /devices/001/telemetry、/devices/001/status、/devices/002/telemetry 等所有以 /devices/ 开头的主题 |
使用通配符时需注意:# 只能放在主题末尾,且前面必须跟一个分隔符(如 /devices/# 合法,/devices# 非法);+ 只能匹配一层,不能跨越层级。此外,主题不能以 / 开头(部分 Broker 允许但建议避免),也不能包含空层级(如 //)。
/devices/+/telemetry 后,你会收到所有设备的遥测数据,但无法在 Broker 层面只接收温度大于 30°C 的消息——这需要在应用层自行过滤。
2.5 典型场景:智能温控系统接入公有云
假设我们要将一批智能温控器接入阿里云 IoT 平台,实现远程监控与指令下发。整体流程如下:
- 设备注册:在云平台创建产品与设备,获取设备三元组(ProductKey、DeviceName、DeviceSecret)。
- 建立连接:温控器通过 MQTT 客户端连接至平台 Broker,使用设备证书完成认证。
- 发布遥测:温控器每 5 秒向主题
/sys/{productKey}/{deviceName}/thing/event/property/post发布 JSON 格式的温度、湿度数据。 - 订阅指令:温控器订阅
/sys/{productKey}/{deviceName}/thing/service/property/set,接收云端下发的目标温度设置。 - 应用订阅:Web 仪表盘订阅
/sys/+/thing/event/property/post,实时展示所有设备数据。
设备发布的数据示例(JSON):
{
"id": "123456",
"version": "1.0",
"params": {
"temperature": 25.6,
"humidity": 48.2
},
"method": "thing.event.property.post"
}
在这个场景中,MQTT 的发布/订阅模型让设备、云平台、应用三者解耦。设备无需关心有多少个应用在读取数据,应用也无需关心设备的具体 IP 地址。新增一个监控大屏时,只需让它订阅对应主题即可,无需修改任何设备端代码。
2.6 误区与复盘
QoS 1 保证消息“至少到达一次”,但可能重复。如果业务对重复数据敏感(如设备指令),应使用 QoS 2 或在应用层做幂等处理。实际项目中,遥测数据通常用 QoS 0 或 1,指令下发建议 QoS 1 并配合消息去重。
例如将设备 ID 直接放在第一层:
device001/temp。当设备数量增长到十万级时,订阅 +/temp 会造成 Broker 路由压力巨大。建议采用“产品类型/地域/设备ID/数据类型”的分层结构,如 factory_a/line_1/device_001/temp,便于按区域或产线订阅。
设备异常断电时,TCP 连接可能不会立即断开。若不设置遗嘱消息,其他订阅者会长时间误以为设备在线。正确做法是在连接时设置遗嘱主题与消息,Broker 检测到异常断开后自动发布遗嘱,通知相关方设备离线。