聊聊 MQTT:物联网的“普通话”
你有没有想过智能家居里的设备之间是怎么“聊天”的比如温度传感器检测到室温过高是怎么通知空调自动打开的又或者你的手机 APP 是怎么远程控制花园里的喷灌系统的这些设备往往来自不同厂商运行在不同的硬件平台上使用不同的编程语言开发。让它们高效、可靠地相互通信并不是一件容易的事。而 MQTT 协议正是为了解决这类问题而生的。什么是 MQTTMQTT 的全称是Message Queuing Telemetry Transport消息队列遥测传输协议。名字听起来很唬人但它的设计目标其实非常朴素用最少的带宽和电量在不可靠的网络环境下实现设备间的可靠通信。它诞生于 1999 年由 IBM 的安迪·斯坦福-克拉克Andy Stanford-Clark和阿兰·尼普Arlen Nipper共同发明。最初的应用场景是石油管道监控——设备位于沙漠深处网络带宽极其有限而且经常断线。是不是很像今天的物联网场景2014 年MQTT 成为了正式的 OASIS 标准后来又被 ISO/IEC 采纳为国际标准。如今从 AWS IoT、Azure IoT Hub 到 Home Assistant、开源项目如 EMQX到处都能看到它的身影。最核心的三个角色MQTT 采用了一种被称为发布/订阅Publish/Subscribe的架构这和我们熟悉的 HTTP “请求/响应” 模式客户端问、服务器答有很大不同。它主要涉及三个角色发布者Publisher负责发送消息的设备。每个发布者只需要把消息发到一个“中间人”那里就行它不需要知道谁会收到这条消息也不关心有多少人会收到。订阅者Subscriber负责接收消息的设备。订阅者告诉“中间人”自己对哪类消息感兴趣然后当有这类消息到来时它就会收到通知。代理Broker这是 MQTT 的核心也就是那个“中间人”。它负责接收所有发布者的消息并根据订阅关系把消息准确地分发给所有订阅者。发布者和订阅者的角色并不是固定的。同一个设备完全可以既发布消息比如上报温度也订阅消息接收控制指令。这种设计带来了一个巨大的好处解耦。发布者和订阅者完全不需要知道彼此的存在也不需要同时在线。发布者可以把消息发给 Broker 就转身离开订阅者也可以等自己上线之后再去 Broker 取消息。这让系统变得非常灵活扩展起来也特别方便。Topic消息的“门牌号”Broker 怎么知道要把消息发给谁呢全靠Topic。Topic 是一个用斜杠分隔的字符串定义了一条消息属于哪个“主题”。例如home/livingroom/temperaturefactory/machine-01/statusvehicle/tesla/model3/battery订阅者可以订阅一个精确的 Topic比如只订阅home/livingroom/temperature。也可以使用通配符来订阅一批 Topic单层通配符。订阅home//temperature会收到home/bedroom/temperature和home/livingroom/temperature但不会收到home/livingroom/light/sensor。#多层通配符。订阅home/#会收到home/下的所有主题包括home/bedroom/temperature和home/bedroom/light/status。通过灵活设计 Topic 的层级结构你可以像设计文件目录一样清晰地组织成千上万个设备的消息。QoS可靠的代价物联网网络是出了名的不稳定。Wi-Fi 会断4G 信号会弱设备可能会突然掉电。MQTT 通过QoSQuality of Service服务质量等级来处理这个问题确保消息能可靠送达。QoS 分为三个等级QoS 0至多一次。消息发出去就不管了不管收没收到。像“实时股票行情”这种丢一两条也没关系的场景可以用它效率最高。QoS 1至少一次。Broker 和客户端会相互确认保证消息至少送达一次但可能重复送达。客户端需要自己处理重复消息。QoS 2恰好一次。通过两次请求-确认的握手确保消息既不丢也不重。这是最安全、但也最耗资源的方式适用于计费、指令等不允许出错的场景。