4. MQTT协议基础:MQTT协议简介、发布/订阅模型、QoS等级、Topic主题设计

好,咱们这一章聊聊MQTT。说实话,在物联网通信这块,MQTT几乎成了事实标准。我最早接触它是在做一个智能路灯项目,当时选型时对比了HTTP、CoAP、MQTT,最后毫不犹豫选了MQTT。为什么?因为它轻量、省带宽、还支持双向通信,特别适合ESP32这种资源受限的设备。

4.1 MQTT协议简介

MQTT全称是Message Queuing Telemetry Transport,消息队列遥测传输。名字挺长,但核心就一句话:一个基于发布/订阅模式的轻量级通信协议

它最早是IBM开发的,用于石油管道监控。你想啊,沙漠里的管道,带宽低、网络不稳定,还得实时传数据——这不就是咱们IoT场景的缩影吗?

MQTT有几个关键特点:

  • 轻量级:最小报文只有2个字节,比HTTP的请求头小太多了
  • 双向通信:设备既能上报数据,也能接收指令
  • 支持QoS:三种服务质量等级,按需选择
  • 遗嘱消息:设备异常断开时,服务器能发通知
  • 保留消息:新订阅者能立即拿到最新数据

核心概念:MQTT通信必须通过一个中间人——Broker(代理服务器)。所有消息都经过Broker转发,设备之间不直接通信。

嗯,这里要注意:Broker就是咱们华为云IoT平台的核心组件。ESP32只管连上Broker,发消息、收消息,剩下的路由、转发、存储,全是Broker的事。

4.2 发布/订阅模型

这个模型,说白了就是「我不直接找你,我把消息扔到公告栏上,谁想看谁看」。

传统HTTP是客户端-服务器模式,客户端请求,服务器响应。但IoT场景里,服务器经常需要主动给设备发指令——比如远程开灯、升级固件。HTTP要实现这个,得靠轮询或者长连接,效率很低。

MQTT的发布/订阅模型就优雅多了:

  • 发布者(Publisher):发送消息的一方,比如ESP32上报温度
  • 订阅者(Subscriber):接收消息的一方,比如手机App接收温度数据
  • 代理(Broker):华为云IoT平台,负责转发
  • 主题(Topic):消息的分类标签,类似快递单上的地址

举个例子:

// ESP32发布温度数据到主题
// 主题:/device/123456/temperature
// 内容:{"value": 25.6, "unit": "celsius"}

// 手机App订阅同一个主题
// 就能收到这条消息

我在项目中遇到过一个问题:多个设备同时往同一个主题发数据,结果订阅端收到的顺序乱了。后来发现是QoS等级设置不一致导致的。这个后面细说。

4.3 QoS等级

QoS(Quality of Service)是MQTT最核心的机制之一。它定义了消息传递的可靠性等级。一共三级:

等级 名称 说明 适用场景
0 至多一次 发完即忘,不确认 传感器数据上报(丢几个没关系)
1 至少一次 确保收到,可能重复 控制指令(重复执行也没事)
2 恰好一次 确保收到且不重复 计费、支付等关键数据

QoS 0:最简单,性能最好。ESP32上报温度数据,每秒一次,丢一两个无所谓。我一般用这个。

QoS 1:发送后会等待Broker确认。如果超时没收到确认,就重发。所以接收方可能收到重复消息。适合开关灯这种指令——多开一次灯也没事。

QoS 2:最可靠,但开销最大。需要四次握手确认。我曾经在项目里用过QoS 2,结果设备多了之后Broker负载飙升。后来发现大部分场景根本不需要。

避坑指南:我曾经在一个项目中,所有消息都用了QoS 2,结果设备多了之后,Broker内存爆了。后来改成:控制指令用QoS 1,数据上报用QoS 0,问题解决。

为什么会这样?因为QoS 2需要Broker维护状态,设备越多,状态表越大。你想想看,如果1000个设备同时用QoS 2,Broker得同时维护几千个会话状态,压力很大。

4.4 Topic主题设计

Topic是MQTT的命脉。设计得好,系统清晰易维护;设计得烂,后期改都改不动。

Topic的格式类似文件路径,用斜杠分隔层级:

/project/device_id/sensor_type/action

举个例子:

/smart_home/room1/temperature/report    // 温度上报
/smart_home/room1/light/control          // 灯光控制
/smart_home/room1/light/status           // 灯光状态

Topic支持通配符:

  • +:匹配单层。比如 /smart_home/+/temperature/report 匹配所有房间的温度上报
  • #:匹配多层。比如 /smart_home/# 匹配所有主题

我个人习惯这样设计Topic:

  1. 按项目分层:最顶层是项目名,避免不同项目冲突
  2. 按设备分层:第二层是设备ID或设备类型
  3. 按数据类型分层:第三层是传感器类型或功能
  4. 按动作分层:最后一层是report(上报)、control(控制)、status(状态)

设计建议:我建议Topic层级不要超过5层。太深了不仅难读,而且Broker匹配效率会下降。另外,Topic名称尽量用英文小写,不要用中文或特殊字符。

嗯,这里还要注意一点:华为云IoT对Topic有自己的一套规则。设备上报数据要用 $oc/devices/{device_id}/sys/properties/report,接收命令要用 $oc/devices/{device_id}/sys/commands/#。这些是平台预定义的,不能随便改。

但你可以自定义Topic,用于设备之间的通信。比如两个ESP32之间传数据,就可以用自定义Topic。不过要注意,自定义Topic需要在华为云平台上提前创建。

最后总结一下:

  • MQTT是IoT通信的首选协议,轻量、双向、可靠
  • 发布/订阅模型让设备解耦,Broker负责转发
  • QoS等级按需选择,别盲目用QoS 2
  • Topic设计要规范,层级清晰,方便扩展

下一章,咱们就动手在ESP32上实现MQTT客户端,连上华为云IoT平台。到时候你会看到,这些理论知识是怎么落地的。