4、MQTT协议基础:理解MQTT协议的工作原理(发布/订阅模式),了解QoS等级,掌握MQTT Broker的概念

好,咱们进入第四章。这一章聊MQTT协议。

说实话,在物联网这个圈子里混,MQTT是绕不开的。我最早接触MQTT是在做一个智能家居网关项目,当时设备端资源紧张得要命,HTTP太重了,CoAP又不太成熟。后来选了MQTT,一用就是好几年。你想想看,一个协议能成为物联网事实标准,肯定有它的道理。

4.1 什么是MQTT?为什么它适合嵌入式设备?

MQTT,全称Message Queuing Telemetry Transport,消息队列遥测传输。名字挺长,但核心就三个字:轻、快、省。

它最早是IBM开发的,用于石油管道监控。那个场景下,带宽窄、信号差、设备还经常断线。你看,这不就是咱们嵌入式设备的典型环境吗?

MQTT的几个关键特点:

  • 协议头极小——最小只有2个字节。我对比过,同样发一条温度数据,HTTP要几百字节,MQTT可能20字节就搞定了。
  • 支持低带宽、高延迟网络——说白了,信号不好也能用。
  • 双向通信——设备不仅能上报数据,还能接收云端下发的指令。
  • 有QoS机制——保证消息不丢,或者至少你知道它丢了。

核心要点:MQTT是发布/订阅模式,不是传统的请求/响应模式。这一点和HTTP完全不同。

4.2 发布/订阅模式——这才是MQTT的灵魂

传统的HTTP通信,是客户端请求,服务器响应。一对一,同步的。

MQTT不一样。它有三个角色:

  • 发布者(Publisher)——发送消息的一方,比如你的温度传感器
  • 订阅者(Subscriber)——接收消息的一方,比如手机App
  • 代理(Broker)——中间人,负责转发消息

发布者和订阅者不需要直接认识。他们通过一个叫主题(Topic)的东西来沟通。

举个例子:

  • 温度传感器每隔5秒发布一条消息到主题 /device/temp
  • 手机App订阅了 /device/temp
  • Broker收到传感器的消息,转发给所有订阅了这个主题的App

你看,传感器和App完全解耦了。传感器不知道谁在收数据,App也不知道数据是谁发的。这就是发布/订阅模式的好处。

我的经验:我在项目中遇到过一个问题——多个设备用同一个主题,结果数据全混了。后来我养成了一个习惯:每个设备用唯一的主题,比如 /device/{deviceId}/temp。这样既清晰又安全。

4.3 MQTT Broker——中间人的角色

Broker,翻译过来叫代理或者服务器。它是MQTT通信的核心。

Broker的职责:

  • 接收发布者的消息
  • 管理订阅关系
  • 把消息转发给对应的订阅者
  • 处理连接、断开、心跳等

市面上常见的Broker有:

Broker名称 特点 适用场景
Mosquitto 轻量、开源、部署简单 本地测试、小规模部署
EMQX 高并发、集群能力强 大规模物联网平台
阿里云IoT 自带Broker、安全认证完善 接入阿里云平台

我个人习惯用Mosquitto做本地调试,用阿里云IoT做正式部署。为什么呢?因为阿里云帮你把Broker维护好了,你只管用就行。

注意:Broker不是MQTT客户端。它不发布消息,也不订阅消息。它只负责转发。这一点很多初学者会搞混。

4.4 QoS等级——消息可靠性的三个档次

QoS,服务质量。说白了就是:这条消息,你希望它多可靠地到达对方?

MQTT定义了三个等级:

QoS等级 名称 含义 发送次数 适用场景
0 至多一次 发完就不管了,不确认 1次 传感器数据,丢了也无所谓
1 至少一次 确保收到,但可能重复 至少1次 控制指令,重复了也能处理
2 恰好一次 确保收到且不重复 2次握手 计费、关键操作

嗯,这里要注意:QoS等级越高,网络开销越大,延迟也越高。

我举个例子你就明白了:

  • QoS 0——就像你往河里扔一块石头,扔完就走,不管它沉没沉。适合温度、湿度这种连续上报的数据,丢一两条无所谓。
  • QoS 1——就像你发微信,对方收到了会回一个"收到"。但如果网络不好,你可能发了两遍,对方收到两次。适合开关灯这种指令,重复执行一次也没关系。
  • QoS 2——就像银行转账,双方反复确认,确保不多转也不少转。适合计费、门锁开闭这种关键操作。

我的建议:在嵌入式设备上,大部分场景用QoS 0就够了。控制指令用QoS 1。QoS 2尽量少用,因为它太耗资源了。我曾经在一个项目里全用了QoS 2,结果设备CPU占用率飙升,后来全改成QoS 0和1,问题就解决了。

4.5 主题(Topic)与通配符

主题是MQTT消息的路由标签。它用斜杠分隔层级,类似文件路径。

比如:

/device/001/temperature
/device/001/humidity
/device/002/temperature

MQTT支持两种通配符:

  • + —— 匹配单层。比如订阅 /device/+/temperature,能收到所有设备的温度数据
  • # —— 匹配多层。比如订阅 /device/#,能收到所有设备的所有数据

避坑指南:我曾经在项目里用 # 通配符订阅了所有主题,结果设备收到了不该收到的消息,导致逻辑混乱。后来我规定:订阅范围要尽量精确,能用 + 就别用 #

4.6 连接、心跳与遗嘱

MQTT的连接过程很简单:

  1. 客户端向Broker发起TCP连接
  2. 发送CONNECT报文,包含客户端ID、用户名密码等
  3. Broker回复CONNACK,确认连接成功

连接建立后,客户端要定期发送心跳(PINGREQ),告诉Broker"我还活着"。Broker回复PINGRESP。如果Broker一段时间没收到心跳,就会认为客户端断线了。

这里有个很实用的功能——遗嘱消息(Will Message)

什么意思呢?就是客户端在连接时,可以预先设置一条消息。如果客户端意外断线,Broker会帮它把这条消息发出去。

比如:一个温度传感器突然掉线了,Broker可以自动发布一条消息 /device/001/status,内容为"offline"。这样云端就知道设备出问题了。

记住:遗嘱消息是MQTT的一大特色。很多物联网平台就是靠它来实现设备在线状态管理的。

4.7 小结

这一章咱们聊了MQTT的核心概念:

  • 发布/订阅模式——解耦了发送方和接收方
  • Broker——消息的中转站
  • QoS等级——0、1、2,按需选择
  • 主题与通配符——灵活的路由机制
  • 心跳与遗嘱——保持连接感知

下一章,咱们会实际动手,在ESP8266上跑通MQTT,连上阿里云。到时候你会发现,理解了这些基础,写代码就是水到渠成的事。