天天看點

MQTT協定詳解及v5.0實踐

本文主要包含了以下内容:

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協定詳解及v5.0實踐
  • 目前主流MQTT Broker開源社群基本已經支援v5.0,并且開源SDK也已經初步支援v5.0,與此同時,國内IoT雲廠商還沒有支援v5.0,但未來已來。

1.3.2 用戶端SDK支援現狀

MQTT協定詳解及v5.0實踐

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應用具備了同步調用的能力,擴充了使用場景,使其具備更多的可能性。

MQTT協定詳解及v5.0實踐
  • 通過topic中包含的messageId比對請求與響應,對業務資料零侵入
  • messageId的生成與比對、逾時控制等邏輯,調用方無感覺
  • 簡化了業務方調用邏輯,擴充了MQTT使用場景。

2.3.3 多種類接入方式

MQTT協定層針對不同場景支援多種MQTT接入方式,同時支援tcp直連、tls、ws、wss等方式接入,用于滿足不同場景接入需求。為了實作更好的網絡穿透性,協定層實作了多協定端口複用,也就是一個端口同時支援多種協定。

MQTT協定詳解及v5.0實踐
  • 邊解析邊判斷,處理效率高;
  • 節約常用端口,實作更好的網絡穿透性
  • 内部能力擴充對裝置側無感覺
  • 針對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擴充參數 使用者屬性
  • 腳本前置解析
  • 全鍊路traceid串聯
離線
  • 異常離線原因推送
  • 動态注冊錯誤推送
  • 豐富接入增值能力,提高接入體驗
  • 後端能力提前ready沉澱,5.0更新可複用已有能力

2.4 未來展望

3. 參考資料

  1. ​​https://developer.ibm.com/zh/technologies/messaging/articles/iot-mqtt-why-good-for-iot/​​
  2. ​​http://docs.oasis-open.org/mqtt/mqtt/v5.0/cs02/mqtt-v5.0-cs02.html​​
  3. ​​http://modelbasedtesting.co.uk/2018/04/09/a-story-of-mqtt-5-0/​​
  4. ​​https://github.com/mqtt/mqtt.github.io/wiki/brokers​​

繼續閱讀