本文主要包含了以下内容:
1)MQTT協定演進曆史及協定特點,總結和分析MQTT協定族的優缺點,分析和總結了為什麼相比于其他協定,MQTT适合IoT,業内支援現狀等。
2)阿裡雲IoT MQTT3和5協定在實踐中的一些關鍵設計及思考。 包括連接配接複用、裝置狀态一緻性、擴充增值能力設計等。
1. MQTT協定詳解
1.1 MQTT協定演進
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。
1.2 MQTT協定族
每一種協定都是在特定上下文、限制下得出的折中設計,從來都沒有完美的協定。 MQTT經過幾十年的發展,針對不同場景已經演進出相對成熟的多版本協定。
1.2.1 MQTTv3
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繼承了。
1.2.2 MQTT-SN
MQTT-SN(Sensor Networks) 是MQTT協定的傳感器網絡版本,最早用在zigBee無線網絡中,主要面對電池供電,有限的處理器能力和存儲能力的裝置。隻有很小的記憶體和CPU,TCP 對于這些裝置來說非常奢侈,甚至無法允許TCP協定棧。 還有一些網絡,比如 zigBee,封包的長度在幾百位元組以下,無法承載太大的資料包。MQTT-SN有主要特點:1) MQTT-SN支援運作在鍊路層、IP、UDP之上。2) QOS增加了-1級别,隻用于傳輸,盡力而為,無保證。3)更豐富且開銷更低的Topic類型。4)網絡架構增加了SN網關。
1.2.3 MQTTv5
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) 服務端能力協商
支援告知裝置端 雲端所支援的功能清單,避免裝置端使用雲端不支援的功能。
1.3 業内現狀
1.3.1 開源社群 & 雲産商

- 目前主流MQTT Broker開源社群基本已經支援v5.0,并且開源SDK也已經初步支援v5.0,與此同時,國内IoT雲廠商還沒有支援v5.0,但未來已來。
1.3.2 用戶端SDK支援現狀
2. MQTT協定層實踐
2.1 MQTT應用架構
主要分為6大子產品:
- 基礎接入子產品:包括多版本協定編解碼、多協定端口複用、會話管理、心跳檢測、連接配接管理等。
- 協定擴充子產品:包括基于自定義協定擴充,實作的一系列擴充功能,包括通道解壓縮、低功耗免ping等。
- 增值消息服務:包括Rrpc、廣播、時鐘同步、腳本前置解析等。
- 業務埋點子產品:裝置行為統計、線上時長聚合、網絡延時診斷等。
- 安全防禦子產品:包括黑名單機制、入口流控等。
- 高可用子產品:包括流量分組排程、容災降級等。
- 運維管控子產品:主要包括流量分組排程、限流管理、連接配接診斷
2.2 協定層設計挑戰
- 裝置狀态一緻性政策設計,包括session管理機制、心跳檢測機制、異地登陸問題、狀态最終一緻性政策。
- 在MQTT釋出/訂閱異步分發模型上,如何滿足多樣的業務場景。例如同步調用、廣播等。
- 如何同時滿足不同場景下裝置對MQTT接入需求,單應用上如何同時支援兩個版本MQTT協定
- MQTTv3協定過于精簡,業務從MQTT3切換到v5的過渡時間,如何擴充協定層能力,提高客戶接入體驗。
2.3 MQTT關鍵政策設計
2.3.1 裝置線上狀态
協定層本地有session管理器來對本地會話進行管理,通過心跳檢測、會話自檢來保證跟裝置之間的連接配接狀态一緻性,目前平台單裝置不支援同時同裝置多端登陸,基于分布式會話,協定層通過分布式會話識别異地登陸,将異常連接配接踢下線。
裝置狀态一緻性政策:裝置到MQTT協定接入層之間是tcp長連接配接,通過心跳機制保證心跳周期内裝置狀态的最終一緻性。同時通過分布式會話版本号,保證分布式會話并發更新安全,通過上行消息/心跳定時觸發會話自檢機制,解決異常情況下本地/分布式會話狀态不一緻的問題。
2.3.2 消息推送模式
MQTT協定是基于PUB/SUB的異步通信模式,針對單裝置緯度實作基礎的釋出/訂閱推送外,還支援了複雜的消息推送方式:RRpc和線上廣播。
在傳統的基于PUB/SUB通信模式的中間件中, 消息的Producer/Consumer隻負責生産和消費,彼此之間不會直接通訊。 而在某些業務場景不僅僅是将消息投遞至訂閱方,訂閱方收到消息後可能還會執行一些操作并傳回結果,PUB/SUB模式下實作這種請求/響應模式會非常繁瑣,在MQTT中通信雙方需要事先協商請求和響應topic。
針對這一痛點,協定層在釋出訂閱模式之上建構了一套Rpc通訊模式,解決開發者痛點。Rrpc模式允許Producer發出消息後,以同步形式等待Consumer消費這條消息并傳回響應,達到類似Rpc的調用效果。Rrpc模式使得MQTT應用具備了同步調用的能力,擴充了使用場景,使其具備更多的可能性。
- 通過topic中包含的messageId比對請求與響應,對業務資料零侵入
- messageId的生成與比對、逾時控制等邏輯,調用方無感覺
- 簡化了業務方調用邏輯,擴充了MQTT使用場景。
2.3.3 多種類接入方式
MQTT協定層針對不同場景支援多種MQTT接入方式,同時支援tcp直連、tls、ws、wss等方式接入,用于滿足不同場景接入需求。為了實作更好的網絡穿透性,協定層實作了多協定端口複用,也就是一個端口同時支援多種協定。
- 邊解析邊判斷,處理效率高;
- 節約常用端口,實作更好的網絡穿透性
- 内部能力擴充對裝置側無感覺
- 針對MQTT協定5和3,通過協定解析也實作了同時相容。
2.3.4 自定義協定擴充
MQTTv3在實際應用中存在一些缺點,而MQTTv5生态的繁榮推廣還需要很長時間的推進, 在MQTT3到5的過渡時間,我們在v3.1.1基礎上通過overlay的方式,提供了擴充套件來解決客戶痛點。
沒有什麼問題不是封一層解決不了的,如果有那就再封一層,思路:
- 通過在建連clientId中擴充ext參數,實作端雲之間能力協商
- 通過擴充消息topic格式,實作支援自定義屬性
- 定義一套ext異常推送topic規範
環節 | 3.1協定擴充 | 5.0對标功能 | 帶來的增值能力 |
建連 | 能力協商 | Broker能力發現 |
|
傳輸 | Topic擴充參數 | 使用者屬性 |
|
離線 |
|
- 豐富接入增值能力,提高接入體驗
- 後端能力提前ready沉澱,5.0更新可複用已有能力
2.4 未來展望
3. 參考資料
- https://developer.ibm.com/zh/technologies/messaging/articles/iot-mqtt-why-good-for-iot/
- http://docs.oasis-open.org/mqtt/mqtt/v5.0/cs02/mqtt-v5.0-cs02.html
- http://modelbasedtesting.co.uk/2018/04/09/a-story-of-mqtt-5-0/
- https://github.com/mqtt/mqtt.github.io/wiki/brokers