3、MQTT基础回顾:MQTT协议原理、QoS等级详解、主题(Topic)与通配符、保留消息与遗嘱消息
3.1 MQTT协议原理:轻量级的“快递员”
MQTT,全称是Message Queuing Telemetry Transport。名字挺长,但说白了,它就是个轻量级的发布/订阅消息协议。
我经常跟团队里的年轻人打比方:MQTT就像一个快递员。你(发布者)把包裹(消息)交给快递站(Broker),快递站再根据包裹上的地址(主题),派送给收件人(订阅者)。整个过程,你不需要知道收件人是谁,收件人也不需要知道你是谁。这就是解耦。
为什么工业物联网里它这么火?因为它的协议头非常小,最小只有2个字节。你想想看,在那些动不动就丢包、带宽窄得像羊肠小道的工业现场,这简直是救星。我曾在一条老旧的RS485线路上跑MQTT,硬是把数据给传回来了,换HTTP?想都别想。
MQTT的核心角色有三个:
- 发布者(Publisher):产生数据的设备,比如PLC、传感器。
- 代理服务器(Broker):消息中转站,负责接收和分发。这是整个系统的核心。
- 订阅者(Subscriber):消费数据的应用,比如SCADA、MES、数据库。
整个通信流程就是:发布者发消息到Broker的一个主题,Broker再把这个消息推送给所有订阅了这个主题的订阅者。简单、高效、解耦。
3.2 QoS等级详解:消息能送到吗?
MQTT定义了三个服务质量等级。说白了,就是决定消息“到底能不能送到,送到几次”。
| QoS等级 | 含义 | 可靠性 | 性能开销 |
|---|---|---|---|
| 0 | 至多一次(At most once) | 最低,可能丢消息 | 最低 |
| 1 | 至少一次(At least once) | 中等,保证送达,但可能重复 | 中等 |
| 2 | 恰好一次(Exactly once) | 最高,保证送达且不重复 | 最高 |
QoS 0: 发出去就不管了。就像你往河里扔块石头,扔完就走,不管它沉没沉。适合那些丢了也无所谓的场景,比如环境温度,丢一两个数据点不影响大局。
QoS 1: 保证消息至少到达一次。Broker收到后会回复一个确认包(PUBACK)。如果发布者没收到确认,就会重发。这会导致订阅者可能收到重复消息。我建议,如果你的应用能处理重复数据(比如用时间戳去重),QoS 1是性价比最高的选择。
QoS 2: 最严格,也最慢。它通过两次确认(PUBREC、PUBREL、PUBCOMP)来确保消息既不丢失也不重复。说实话,我在实际项目中很少用QoS 2。为什么?因为性能开销太大了。只有在控制指令这种“发错一次就完蛋”的场景下,我才会考虑它。比如,给机械臂发“急停”指令,必须用QoS 2。
3.3 主题(Topic)与通配符:消息的“门牌号”
主题,就是消息的地址。它是个字符串,用“/”分层。比如:
factory/line1/robot/arm/temperature
factory/line1/robot/arm/status
factory/line2/robot/arm/temperature
这种分层结构,让消息管理变得非常清晰。你可以把不同车间、不同产线、不同设备的数据,都组织到一棵“主题树”里。
但问题来了:如果我想订阅“所有机器人的温度”,难道要一个一个写主题吗?不用。MQTT提供了两个通配符:
- 单层通配符(+):匹配一层。比如订阅
factory/+/robot/arm/temperature,就能匹配到line1和line2的温度。 - 多层通配符(#):匹配剩余所有层。比如订阅
factory/#,就能收到factory下所有主题的消息。
我个人习惯,在调试阶段用 # 来抓取所有数据,非常方便。但生产环境,千万别这么干!为什么?因为订阅 # 会收到Broker上所有的消息,流量巨大,客户端根本扛不住。
3.4 保留消息与遗嘱消息:Broker的“记忆”与“遗言”
这两个特性,是MQTT在工业场景中非常好用的“杀手锏”。
保留消息(Retained Message):
想象一下,你新装了一个温度传感器,它每隔10秒发一次数据。但你的监控系统是后来才启动的。它一启动,能立刻拿到当前温度吗?
如果没有保留消息,它必须等10秒,等传感器下一次发布。有了保留消息,传感器可以在发布时设置 retain=true。Broker会记住这条消息。当新的订阅者上线时,Broker会立刻把这条“保留消息”推送给它。
说白了,保留消息就是Broker的“记忆”。它让新订阅者能立即获取到设备的“最新状态”,而不是傻等。我在做设备状态监控时,每个设备都会发布一条保留消息,内容就是它的当前状态(运行/停止/故障)。这样,任何客户端一上线,就能立刻看到所有设备的实时状态。
遗嘱消息(Will Message):
这个特性,我称之为“最后的遗言”。
设备在连接Broker时,可以设置一个遗嘱消息。如果设备非正常断开(比如掉电、断网),Broker会替它发布这条遗嘱消息。
举个例子:你有一个PLC,它正常运行时,每隔5秒发布一次心跳。同时,它在连接时设置了遗嘱消息:topic: factory/line1/plc/status, payload: offline。如果PLC突然掉线,Broker检测到连接断开,就会立刻发布这条遗嘱消息。你的监控系统订阅了这个主题,就能立刻知道“PLC离线了”,从而触发报警。
/status 或 /will 后缀,方便订阅者区分。
嗯,到这里,MQTT的基础就回顾完了。这些概念,在后面的OPC UA与MQTT融合通信中,会反复用到。尤其是主题设计和QoS选择,直接决定了你整个系统的稳定性和实时性。别急,后面我们一步步实战。