2. MQTT协议基础概念:Broker、Client、Topic、Payload、Session、Will Message等核心术语详解
好,咱们正式开始聊MQTT的核心概念。说实话,很多初学者一上来就被这些术语搞懵了。什么Broker、Client、Topic……听着像是一堆专业黑话。其实没那么复杂,你把它想象成一个「消息快递系统」,一下子就通了。
我个人习惯把MQTT比作一个「邮局」。Client就是寄信人和收信人,Broker就是邮局本身,Topic就是地址,Payload就是信的内容。嗯,咱们一个一个拆开讲。
2.1 Broker——消息的中枢神经
Broker,说白了就是MQTT服务器。所有消息都得经过它。它不生产消息,它只是消息的搬运工。
我在项目中遇到过一种情况:团队里有人把Broker和Client搞混了,结果调试了一整天,发现消息根本没发出去。为什么?因为Client之间不直接通信,所有数据都得走Broker中转。
Broker的核心职责:
- 接收Client发来的消息
- 根据Topic将消息转发给订阅者
- 管理Client的会话状态
- 处理遗嘱消息(Will Message)
常见的Broker实现有Mosquitto、EMQX、VerneMQ。我个人偏爱Mosquitto,轻量、稳定,适合嵌入式场景。
2.2 Client——消息的发送者与接收者
任何连接到Broker的设备,都叫Client。它可以是一个传感器、一部手机、一台服务器,甚至是一个微服务。
Client有两种角色:
- Publisher(发布者):发送消息的一方
- Subscriber(订阅者):接收消息的一方
你想想看,同一个Client可以同时扮演两种角色。比如一个温度传感器,它既发布温度数据,又订阅控制指令。这在IoT场景里太常见了。
我的经验:设计Client时,一定要考虑断线重连机制。我曾经见过一个设备,网络一抖就再也连不回来了,最后只能派人去现场重启。嗯,这种坑踩过一次就够了。
2.3 Topic——消息的地址标签
Topic就是消息的「地址」。它用斜杠分隔层级,比如:
sensor/temperature/room1
sensor/humidity/room2
device/light/status
Topic支持通配符:
+:匹配单层。比如sensor/+/room1匹配sensor/temperature/room1和sensor/humidity/room1#:匹配多层。比如sensor/#匹配所有以sensor/开头的Topic
我记得有一次,团队里有人把Topic设计成 data/2024/01/15/temperature,结果订阅时用了 data/#,一下子把所有历史数据都拉下来了。嗯,Topic设计要谨慎,层级别太深,也别太浅。
避坑指南:Topic不要以斜杠开头或结尾。比如 /sensor/temp 和 sensor/temp/ 都是不规范的做法。我曾经因为这个导致订阅匹配失败,排查了半天才发现是斜杠的问题。
2.4 Payload——消息的实体内容
Payload就是消息里真正要传输的数据。它可以是任何格式:JSON、XML、二进制、纯文本……MQTT本身不限制。
我个人建议用JSON,可读性好,解析方便。比如:
{
"device_id": "sensor_01",
"temperature": 25.6,
"humidity": 60.2,
"timestamp": 1700000000
}
但要注意,Payload大小有限制。默认情况下,MQTT最大支持256MB的Payload。不过在实际项目中,我建议控制在1KB以内。为什么?因为大消息会占用带宽,增加延迟,还容易导致内存溢出。
我的习惯:Payload里只放必要字段。别把整个设备状态都塞进去。我曾经见过一个Payload,里面包含了设备型号、固件版本、WiFi信号强度……其实订阅者只需要温度数据。浪费带宽不说,还增加了解析负担。
2.5 Session——Client与Broker的「记忆」
Session就是Client和Broker之间的「会话」。它记录了订阅关系、未送达的消息等状态。
Session有两种模式:
| 模式 | 说明 | 适用场景 |
|---|---|---|
| Clean Session = true | 每次连接都是全新会话,断开后Broker不保留任何状态 | 临时设备、测试环境 |
| Clean Session = false | Broker保留会话状态,断线重连后恢复 | 生产环境、需要持久订阅的设备 |
你想想看,如果一个传感器每5秒发一次数据,断线后重连,你希望它丢失这5秒的数据吗?当然不希望。所以生产环境中,我一般建议用持久会话。
关键点:持久会话会占用Broker的内存。如果设备数量很大(比如10万+),要评估Broker的承载能力。我曾经遇到过Broker内存爆掉的情况,就是因为持久会话太多,没及时清理。
2.6 Will Message——设备的「遗言」
Will Message,中文叫遗嘱消息。它是Client在连接时预先设定的一条消息。当Client意外断开时,Broker会替它把这条消息发出去。
举个例子:
// Client连接时设置遗嘱消息
client.connect({
will: {
topic: 'device/status',
payload: JSON.stringify({ device_id: 'sensor_01', status: 'offline' }),
qos: 1,
retain: true
}
});
当这个传感器突然掉线,Broker就会向 device/status 这个Topic发送一条消息,内容是 {"device_id": "sensor_01", "status": "offline"}。其他订阅了这个Topic的Client就能立刻知道:哦,那个传感器挂了。
避坑指南:遗嘱消息只在「意外断开」时触发。如果Client主动发送DISCONNECT报文正常断开,遗嘱消息不会发送。我曾经踩过这个坑:调试时手动断开连接,发现遗嘱没发,还以为是Broker的bug,结果是自己没搞清楚触发条件。
另外,遗嘱消息的QoS和Retain标志也要注意。我建议QoS至少设为1,确保消息能送达。Retain设为true的话,新订阅者一上来就能收到这个离线状态,非常实用。
2.7 小结
好了,核心术语咱们过了一遍。Broker是中枢,Client是端点,Topic是地址,Payload是内容,Session是记忆,Will Message是遗言。这六个概念,是理解MQTT的基石。
你想想看,掌握了这些,再看MQTT的报文交互,是不是清晰多了?下一章咱们就深入报文结构,看看这些概念在网络上是怎么传输的。
嗯,今天就到这儿。有问题随时交流。