MQTT协议核心概念详解
说实话,MQTT 协议看起来简单,但坑不少。我带过不少团队,发现很多人卡在概念理解上。今天我把 Broker、Topic、Payload 这些核心概念掰开揉碎了讲。
先看一张整体架构图,心里有个谱。
1. Broker 服务器
Broker 就是 MQTT 的中央枢纽。所有消息都经过它转发。你可以把它想象成一个邮局——发布者把信投进去,订阅者从里面取信。
我最早用 Mosquitto 做 Broker,后来项目大了换成 EMQX。选型时要注意并发量。个人项目用 Mosquitto 就够了,工业级场景建议用 EMQX 或 VerneMQ。
Broker 的核心职责:
- 接收发布者的消息
- 根据 Topic 匹配订阅者
- 转发消息给所有匹配的订阅者
- 管理客户端连接和会话状态
- 处理心跳超时和断线重连
选型建议:ESP32 项目推荐用 Mosquitto 或 EMQX。Mosquitto 轻量,EMQX 功能全。我习惯先在本地搭 Mosquitto 调试,上线再切 EMQX。
2. Topic 主题
Topic 是消息的分类标签。它用斜杠分层,像文件路径一样。比如:
sensor/temperature
sensor/humidity
home/livingroom/light
Topic 支持通配符,这是 MQTT 的杀手锏:
- +:匹配单层。比如
sensor/+/temperature匹配sensor/room1/temperature - #:匹配多层。比如
sensor/#匹配所有 sensor 下的主题
我在项目中吃过亏。有一次 Topic 层级设计太深,导致订阅匹配性能下降。后来总结出经验:层级控制在 3-4 层最合适。
注意:Topic 不能以 / 开头或结尾。不要用中文 Topic,兼容性差。我见过有人用中文 Topic,结果某些 Broker 解析报错。
3. Payload 消息体
Payload 就是消息的实际内容。MQTT 对 Payload 格式没限制,可以是文本、二进制、JSON 等。
我个人强烈建议用 JSON 格式。结构清晰,解析方便。比如:
{
"device_id": "esp32_001",
"temperature": 25.6,
"humidity": 60.2,
"timestamp": 1700000000
}
Payload 大小要注意。MQTT 协议最大支持 256MB,但实际项目中建议控制在 1KB 以内。ESP32 内存有限,太大的 Payload 会撑爆缓冲区。
经验之谈:Payload 里一定要带时间戳。我遇到过设备上报数据,Broker 延迟转发,没有时间戳根本不知道数据是什么时候采集的。
4. Client ID
Client ID 是每个 MQTT 客户端的唯一标识。Broker 靠它区分不同设备。
Client ID 必须唯一。如果两个客户端用相同的 ID 连接,前一个会被踢下线。我在调试时经常遇到这个问题——开了两个终端用同一个 ID 连接,结果互相踢。
ESP32 上我习惯用 MAC 地址或芯片唯一 ID 生成 Client ID:
// 用 MAC 地址生成 Client ID
String clientId = "esp32_" + WiFi.macAddress();
clientId.replace(":", "");
Client ID 命名规范:
- 长度 1-23 个字符
- 只允许字母、数字、下划线、连字符
- 区分大小写
- 建议包含设备类型或位置信息
5. Session 会话
Session 是 Broker 为每个客户端维护的状态信息。包括订阅列表、未送达的消息等。
MQTT 有两种会话模式:
| 模式 | Clean Session | 特点 | 适用场景 |
|---|---|---|---|
| 持久会话 | false | Broker 保存订阅和离线消息 | 需要接收离线消息的设备 |
| 临时会话 | true | 断开后清除所有状态 | 传感器等只上报数据的设备 |
我建议传感器设备用临时会话。省内存,省带宽。控制类设备用持久会话,防止掉线后丢失指令。
避坑:持久会话会占用 Broker 内存。设备量大的时候要注意。我曾经有个项目挂了 5000 个持久会话,Broker 内存直接爆了。
6. Keep Alive 心跳机制
Keep Alive 是客户端和 Broker 之间的保活机制。客户端定期发送心跳包,告诉 Broker "我还活着"。
心跳间隔由客户端在连接时指定。一般设 30-60 秒。Broker 如果在 1.5 倍间隔内没收到心跳,就认为客户端掉线了。
ESP32 上配置心跳很简单:
// 设置心跳间隔为 30 秒
client.setKeepAlive(30);
心跳太短浪费流量,太长影响掉线检测。我一般设 30 秒,兼顾实时性和资源消耗。
调试技巧:用 Wireshark 抓包看 MQTT 心跳包。正常情况每 30 秒会看到一个 PINGREQ 和 PINGRESP 包。如果看不到,说明心跳机制有问题。
小结
这六个概念是 MQTT 的基石。Broker 是中心,Topic 是通道,Payload 是数据,Client ID 是身份,Session 是状态,Keep Alive 是保活。理解透它们,MQTT 就算入门了。