MQTT協議詳解及v5.0實踐

AIoT2688發表於2022-08-24

MQTT是基於TCP/IP協議棧構建的非同步通訊訊息協議,是一種輕量級的釋出、訂閱資訊傳輸協議。可在不可靠的網路環境中進行擴充套件,適用於裝置硬體儲存空間或網路頻寬有限的場景。 MQTT已逐漸成為IoT領域最熱門的協議,也是國內外各大物聯網平臺最主流的傳輸協議,阿里雲IoT平臺很多裝置都是透過MQTT接入。 本文將詳細介紹MQTT協議的歷史演進,以及阿里雲IoT平臺在MQTT協議層實踐中的一些關鍵設計及思考。


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

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接入的。

image

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 開源社群 & 雲產商

image

  • 目前主流MQTT Broker開源社群基本已經支援v5.0,並且開源SDK也已經初步支援v5.0,與此同時,國內IoT雲廠商還沒有支援v5.0,但未來已來。

1.3.2 客戶端SDK支援現狀

image

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

image

  • 透過topic中包含的messageId匹配請求與響應,對業務資料零侵入
  • messageId的生成與匹配、超時控制等邏輯,呼叫方無感知
  • 簡化了業務方呼叫邏輯,擴充套件了MQTT使用場景。


2.3.3 多種類接入方式

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

image

  • 邊解析邊判斷,處理效率高;
  • 節約常用埠,實現更好的網路穿透性
  • 內部能力擴充套件對裝置側無感知
  • 針對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串聯

離線

Ext系統Topic

錯誤反饋

  • 異常離線原因推送
  • 動態註冊錯誤推送
  • 豐富接入增值能力,提高接入體驗
  • 後端能力提前ready沉澱,5.0升級可複用已有能力

2.4 未來展望

當前阿里雲IoT平臺協議層已支援了MQTT主流協議,並支援了多種協議接入方式,但還存在一些會進一步最佳化的地方:1)更豐富的訊息質量模型,例如支援QoS2,支援訊息優先順序等; 2)完善低功耗領域的閘道器側支援,可以跟SDK/邊緣閘道器合作,支援MQTT-SN協議等

3. 參考資料

  1. https://developer.ibm.com/zh/technologies/messaging/articles/iot-mqtt-why-good-for-iot/


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70017009/viewspace-2911805/,如需轉載,請註明出處,否則將追究法律責任。

相關文章