首页 > 云计算 > 公有云实践 > MQTT协议详解及v5.0实践——实践类
MQTT是基于TCP/IP协议栈构建的异步通信消息协议,是一种轻量级的发布、订阅信息传输协议。可在不可靠的网络环境中进行扩展,适用于设备硬件存储空间或网络带宽有限的场景。 MQTT已逐渐成为IoT领域最热门的协议,也是国内外各大物联网平台最主流的传输协议,阿里云IoT平台很多设备都是通过MQTT接入。 本文将详细介绍MQTT协议的历史演进,以及阿里云IoT平台在MQTT协议层实践中的一些关键设计及思考。
本文主要包含了以下内容:
1)MQTT协议演进历史及协议特点,总结和分析MQTT协议族的优缺点,分析和总结了为什么相比于其他协议,MQTT适合IoT,业内支持现状等。
2)阿里云IoT MQTT3和5协议在实践中的一些关键设计及思考。 包括连接复用、设备状态一致性、扩展增值能力设计等。
MQTT最初由IBM于20世纪90年代发明,最初是用于石油管道的传感器与卫星之间数据传输。MQTT v3.1.1于2014.10月正式发布,与此同时v3.1.1已成为OASIS协议标准(就是3.1.1已升级为国际物联网标准)。正如HTTP为人们通过web分享信息铺平了道路一样,MQTT标准化能将几十亿低成本、IoT设备连接到网络。毫无疑问,MQTT是当前最主流、增长最迅速的IoT应用层传输协议,目前,阿里云IoT平台许多在线设备都是通过MQTT接入的。

MQTT v5.0 于2018.5月正式发布,2019年3月,v5.0 成为了新的 OASIS 标准。v5.0在 v3.1.1的基础上做了较大的改变且不做向下兼容,显然是有太多的新东西要被引入,所有现有的实现要重新实现。 此次通过的 v5.0是自2014年的v3.1.1以来最重要的协议升级,新协议能适应近年来行业发展的新需求,同时也为未来物联网行业发展的做了协议上的准备。 阿里云IoT平台从2020.1月开始支持 MQTT5.0。
每一种协议都是在特定上下文、约束下得出的折中设计,从来都没有完美的协议。 MQTT经过几十年的发展,针对不同场景已经演进出相对成熟的多版本协议。
MQTTv3协议是为在低带宽、不可靠的网络上工作的传感器而设计的基于TCP的应用层协议,适用于IoT场景。 MQTT报文设计紧凑,可在严重受限的硬件设备和低带宽/高延迟的网络上实现稳定传输。它具有以下几项重要特性:使用发布/订阅消息模式,支持一对多的消息分发,解除设备和业务之间的耦合; 报文格式设计精简, 适用于小规模数据传输以及资源受限的IoT设备。 固定头部是2字节,开销很小,支持QoS0、QoS1、QoS2 三种消息QoS。
MQTT3.1.1在MQTTv3基础上引入了一些新特性, 主要包括:clientId优化,支持broker给设备指定clientId,增大了clientId最大长度。ack响应优化,connect ack中引入session Present标识,告诉设备当前broker有上次连接的会话信息,设备可以根据这个标记减少重复订阅等步骤。设备能够在等broker返回connect ack之前发布消息,这个特性有点类似tls的false start, 适用于对于突发模式的设备端。
MQTTv3/v3.1.1 在实际应用中存在以下不足:1)错误码设计的不够完整,设备难以完整感知到broker的处理异常;2)不支持设备跟broker之间的能力发现/协商,broker不能提供可选能力等。3)协议设计的过于精简,没有预留扩展空间,无法直接在协议层做扩展,协议能力相对简陋。4)对于一些高阶能力支持不够,例如协议层缺乏流控、优先级、报头压缩等功能。5)MQTT3是基于TCP的应用层协议,TCP固有的一些缺点也被MQTT继承了。
MQTT-SN(Sensor Networks) 是MQTT协议的传感器网络版本,最早用在zigBee无线网络中,主要面对电池供电,有限的处理器能力和存储能力的设备。只有很小的内存和CPU,TCP 对于这些设备来说非常奢侈,甚至无法允许TCP协议栈。 还有一些网络,比如 zigBee,报文的长度在几百字节以下,无法承载太大的数据包。MQTT-SN有主要特点:1) MQTT-SN支持运行在链路层、IP、UDP之上。2) QOS增加了-1级别,只用于传输,尽力而为,无保证。3)更丰富且开销更低的Topic类型。4)网络架构增加了SN网关。
MQTT 5.0在协议层提供了更大的自定义扩展空间,平台基于扩展点可支持更丰富的协议能力。v3.1版本中,只能通过overlay方式,在业务层提供扩展能力。
MQTT5.0 主要特点如下:
|
设计目标 |
功能点 |
备注 |
|
提高错误反馈能力 |
Reason code& string on all ACKs |
ack有了错误码,端上处理可以更灵活。例如qos1如果被限流,端上可以根据code主动减缓速率 |
|
Server disconnect |
端上根据断开原因,能采用更合理的重连退避策略(是否重连、重连间隔、redirect地址等) | |
|
增加可扩展能力 |
Payload format and content type |
丰富消息格式,用户更友好 |
|
Message expiry |
业务层也可以自己做,协议层原生支持更优雅 | |
|
Subscription ID |
客户端可以建立订阅标识符与消息处理程序的映射,提高客户端topic匹配速度 | |
|
Will delay |
类似疲劳度策略,一定时间内,设备如果重连成功,则不发遗嘱。 | |
|
Server Keep Alive |
服务端可以根据自身负载情况,动态调整max keepalive,实现动态keepalive | |
|
Assigned ClientID |
支持云端给设备生成clientId | |
|
Server reference |
1.跟http location类似 2.接入层支持切流和调度会更加灵活,不用再依赖DNS | |
|
User properties |
给业务层提供极高的可扩展性 | |
|
提高系统的伸缩性 |
Session expiry |
便于快速重连场景下client对clean session的使用和管理 |
|
Shared Subscriptions |
南向类似设备广播,北向类似服务端订阅 | |
|
Optional Server feature availability |
支持端-云能力协商 | |
|
优化资源受限和小客户端接入 |
Subscription options |
提供更细粒度的订阅策略,例如设备侧来决定是否允许自发自收 |
|
Topic Alias |
类似hpack,减少带宽开销 | |
|
Flow control |
设备侧可配置的传输策略,可根据自身资源情况,灵活指定消息传输限制 | |
|
Maximum Packet Size | ||
|
No retry for QoS 1 and 2 messages |
优化QoS1 消息重试策略 | |
|
常见范式下沉至协议层 |
Request / Response |
user properties即可支持,broker不感知 |
|
Enhanced authentication |
支持增强认证(例如支持Kerberos 认证、SCRAM认证) |
1) 用户属性
设备上下行消息的时候支持携带用户自定义的属性,用户可以添加两端约定的属性数据,类似于MQ的标签,其中云端在转发应用消息时会保持所有用户属性的先后顺序。
2) 主题别名
设备上报消息的topic常常相对比较固定,数量不会特别多,那么只需首次发送消息的时候,通过携带Topic别名告知对端, 下次发送消息的时候,这个topic将会使用这个Topic别名的值来代替,即可减少上报Publish消息的报头。 通过将主题缩减为一个整型的数值可以达到减小MQTT报头大小的作用,从而减小传输流量开销,非常适用于带宽资源受限的设备。
3)请求/响应模式
MQTT3.1版本中通信双方需要事先协商好请求主题和响应topic。 MQTT5 新增了响应主题和相关数据,接收方只需关注怎么处理请求,而不用事先协商或考虑好怎么将响应正确返回给请求方。
4) 响应报文原因码和原因字符串
mqtt 3.1协议中原因码的种类较少,这些原因码所能表示的含义很少,并且mqtt3.1不支持服务端通过disconnect报文断开连接,导致设备端仅根据响应难以定位问题。 mqtt5.0有近50个原因码,绝大部分ack响应报文都包含了原因码,设备可以根据这些丰富的原因码定位请求是否成功以及问题。 MQTT5议能反馈更多的错误信息到端上,并且支持云端通过disconnect报文主动断开连接, 设备端知道服务端发生了什么,因而能更灵活的应对。
5) 服务端能力协商
支持告知设备端 云端所支持的功能列表,避免设备端使用云端不支持的功能。


主要分为6大模块:
协议层本地有session管理器来对本地会话进行管理,通过心跳检测、会话自检来保证跟设备之间的连接状态一致性,当前平台单设备不支持同时同设备多端登陆,基于分布式会话,协议层通过分布式会话识别异地登陆,将异常连接踢下线。
设备状态一致性策略:设备到MQTT协议接入层之间是tcp长连接,通过心跳机制保证心跳周期内设备状态的最终一致性。同时通过分布式会话版本号,保证分布式会话并发更新安全,通过上行消息/心跳定时触发会话自检机制,解决异常情况下本地/分布式会话状态不一致的问题。
MQTT协议是基于PUB/SUB的异步通信模式,针对单设备纬度实现基础的发布/订阅推送外,还支持了复杂的消息推送方式:RRpc和在线广播。
在传统的基于PUB/SUB通信模式的中间件中, 消息的Producer/Consumer只负责生产和消费,彼此之间不会直接通讯。 而在某些业务场景不仅仅是将消息投递至订阅方,订阅方收到消息后可能还会执行一些操作并返回结果,PUB/SUB模式下实现这种请求/响应模式会非常繁琐,在MQTT中通信双方需要事先协商请求和响应topic。
针对这一痛点,协议层在发布订阅模式之上构建了一套Rpc通讯模式,解决开发者痛点。Rrpc模式允许Producer发出消息后,以同步形式等待Consumer消费这条消息并返回响应,达到类似Rpc的调用效果。Rrpc模式使得MQTT应用具备了同步调用的能力,扩展了使用场景,使其具备更多的可能性。

MQTT协议层针对不同场景支持多种MQTT接入方式,同时支持tcp直连、tls、ws、wss等方式接入,用于满足不同场景接入需求。为了实现更好的网络穿透性,协议层实现了多协议端口复用,也就是一个端口同时支持多种协议。

MQTTv3在实际应用中存在一些缺点,而MQTTv5生态的繁荣推广还需要很长时间的推进, 在MQTT3到5的过渡时间,我们在v3.1.1基础上通过overlay的方式,提供了扩展套件来解决客户痛点。
没有什么问题不是封一层解决不了的,如果有那就再封一层,思路:
|
环节 |
3.1协议扩展 |
5.0对标功能 |
带来的增值能力 |
|
建连 |
能力协商 |
Broker能力发现 |
|
|
传输 |
Topic扩展参数 |
用户属性 |
|
|
离线 |
Ext系统Topic |
错误反馈 |
|
当前阿里云IoT平台协议层已支持了MQTT主流协议,并支持了多种协议接入方式,但还存在一些会进一步优化的地方:1)更丰富的消息质量模型,例如支持QoS2,支持消息优先级等; 2)完善低功耗领域的网关侧支持,可以跟SDK/边缘网关合作,支持MQTT-SN协议等
物联网平台产品介绍详情:

阿里云物联网平台客户交流群
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70017009/viewspace-2911805/ ,如需转载,请注明出处,否则将追究法律责任。