雲棲號資訊:【點擊查看更多行業資訊】
在這裏您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!
隨着 5G 時代的來臨,萬物互聯的偉大構想正在成爲現實。聯網的 物聯網設備 在 2018 年已經達到了 70 億1,在未來兩年,僅智能水電氣表就將超過10億2。
海量的設備接入和設備管理對網絡帶寬、通信協議以及平臺服務架構都帶來了很大挑戰。對於 物聯網協議 來說,必須針對性地解決物聯網設備通信的幾個關鍵問題:其網絡環境複雜而不可靠、其內存和閃存容量小、其處理器能力有限。
MQTT 協議 是基於發佈/訂閱模式的物聯網通信協議,憑藉簡單易實現、支持 QoS、報文小等特點,佔據了物聯網協議的半壁江山:
MQTT 協議的誕生
MQTT was created by Andy Stanford-Clark of IBM, and Arlen Nipper (then of Arcom Systems, later CTO of Eurotech).^3
據 Arlen Nipper 在一 IBM Podcast 上的自述,MQTT 原名是 MQ TT, 注意 MQ 與 TT之間的空格,其全稱爲: MQ Telemetry Transport,是九十年代早期,他在參與 Conoco Phillips 公司的一個原油管道數據採集監控系統(pipeline SCADA system)時,開發的一個實時數據傳輸協議。它的目的在於讓傳感器通過帶寬有限的 VSAT ,與 IBM 的 MQ Integrator 通信。由於 Nipper 是遙感和數據採集監控專業出身,所以按業內慣例給了個 MQ TT 的名字。
MQTT 協議設計原則
按照 Nipper 的介紹,MQTT 必須簡單容易實現,必須支持 QoS(設備網絡環境複雜),必須輕量且省帶寬(因爲那時候帶寬很貴),必須數據無關(不關心 Payload 數據格式),必須有持續地會話感知能力(時刻知道設備是否在線)。下面將介紹 MQTT (3.1.1 版本) 的幾個核心特色,分別對應了這幾個設計原則的實現。
靈活的發佈訂閱和主題設計
發佈訂閱模式是傳統 Client/Server 模式的一種解耦方案。發佈者通過 Broker 與消費者之間通信,Broker 的作用是將收到的消息通過某種過濾規則,正確地發送給消費者。發佈/訂閱模式 相對於 客戶端/服務器模式 的好處在於:
- 發佈者和消費者之間不必預先知道對方的存在,比如不需要預先溝通對方的 IP Address 和 Port
- 發佈者和消費者之間不必同時運行。因爲 Broker 是一直運行的。
在 MQTT 協議裏,上面提到的 過濾規則 是 Topic。比如:所有發佈到 news 這個 Topic 的消息,都會被 Broker 轉發給已經訂閱了 news 的訂閱者:
上圖中訂閱者預先訂閱了 news,然後發佈者向 Broker 發佈了一條消息 "some msg" 並指定發佈到 news 主題,Broker 通過 Topic 匹配,決定將這條消息轉發給訂閱者。
MQTT 的 Topic 有層級結構,並且支持通配符 + 和 #:
1.+ 是匹配單層的通配符。比如 news/+ 可以匹配 news/sports,news/+/basketball 可匹配到 news/sports/basketball。
2.# 是一到多層的通配符。比如 news/# 可以匹配 news、 news/sports、news/sports/basketball 以及 news/sports/basketball/x 等等。
MQTT 的主題是不要預先創建的,發佈者發送消息到某個主題、或者訂閱者訂閱某個主題的時候,Broker 就會自動創建這個主題。
帶寬消耗最小化
MQTT 協議將協議本身佔用的額外消耗最小化,消息頭部最小隻需要佔用 2 個字節。
MQTT 的消息格式分三部分:
- 固定長度頭部,2 個字節,所有消息類型裏都有
- 可變長度頭部,只有某些消息類型裏有
- Payload,只有某些消息類型裏有
MQTT 的主要消息類型有:
- CONNECT / CONNACK
- PUBLISH / PUBACK
- SUBSCRIBE / SUBACK
- UNSUBSCRIBE / UNSUBACK
- PINGREQ / PINGRESP
- DISCONNECT
其中 PINGREQ / PINGRESP 和 DISCONNECT 報文是不需要可變頭部的,也沒有 Payload,也就是說它們的報文大小僅僅消耗 2 個字節。
在 CONNECT 報文的可變長度頭部裏,有個 Protocol Version 的字段。爲了節省空間,只有一個字節。所以版本號不是按照字符串 "3.1.1" 存放的,而是使用數字 4 來表示 3.1.1 版本。
三個可選的 QoS 等級
爲適應設備不同的網絡環境,MQTT 設計了 3 個 QoS 等級,0, 1, 2:
- At most once (0)
- At least once (1)
- Exactly once (2)
QoS 0 是一種 "fire and forget" 的消息發送模式:Sender (可能是 Publisher 或者 Broker) 發送一條消息之後,就不再關心它有沒有發送到對方,也不設置任何重發機制。
QoS 1 包含了簡單的重發機制,Sender 發送消息之後等待接收者的 ACK,如果沒收到 ACK 則重新發送消息。這種模式能保證消息至少能到達一次,但無法保證消息重複。
QoS 2 設計了略微複雜的重發和重複消息發現機制,保證消息到達對方並且嚴格值到達一次。
會話保持
MQTT 沒有假設設備或 Broker 使用了 TCP 的保活機制^4,而是設計了協議層的保活機制:在 CONNECT 報文裏可設置 Keepalive 字段,來設置保活心跳包 PINGREQ/PINGRESP 的發送時間間隔。當長時間無法收到設備的 PINGREQ 的時候,Broker 就會認爲設備已經下線。
總的來說,Keepalive 有兩個作用:
- 發現對端死亡或者網絡中斷
- 在長時間無消息交互的情況下,保持連接不被網絡設備斷開
對於那些想要在重新上線後,重新收到離線期間錯過的消息的設備,MQTT 設計了持久化連接:在 CONNECT 報文裏可設置 CleanSession 字段爲 False,則 Broker 會爲終端存儲:
- 設備所有的訂閱
- 還未被設備確認的 QoS1 和 QoS 消息
- 設備離線時錯過的消息
在線狀態感知
MQTT 設計了遺願(Last Will) 消息,讓 Broker 在發現設備異常下線的情況下,幫助設備發佈一條遺願消息到指定的主題。
實際上在某些 MQTT 服務器的實現裏 (比如 EMQ X),設備上線或下線的時候 Broker 會通過某些系統主題發佈設備狀態更新,更符合實際應用場景。
開源 MQTT 服務器如何選擇
到目前爲止,比較流行的開源 MQTT 服務器有幾個:
- Eclipse Mosquitto
使用 C 語言實現的 MQTT 服務器。Eclipse 組織還還包含了大量的 MQTT 客戶端項目:https://www.eclipse.org/paho/#
- EMQ X
使用 Erlang 語言開發的 MQTT 服務器,內置強大的規則引擎,支持許多其他 IoT 協議比如 MQTT-SN、 CoAP、LwM2M 等。
- Mosca
使用 Node.JS 開發的 MQTT 服務器,簡單易用。
- VerneMQ
同樣使用 Erlang 開發的 MQTT 服務器.
從支持 MQTT 5.0、穩定性、擴展性、集羣能力等方面考慮,EMQ X 的表現應該是最好的:
- 使用 Erlang OTP 開發,容錯能力好 (電信領域久經考驗的語言,曾經做出過 99.9999999% 可用性的交換機設備^5)
- 官方有大量的擴展插件可供擴展。有很多認證插件,數據存儲(backend)插件可供選擇。可支持各種關係型數據庫,NoSQL 數據庫,以及常- 見消息隊列如 Kafka,RabbitMQ,Pulsar 等
- 支持集羣,支持節點水平擴展
- 單節點支持 2000K 併發連接
- 支持規則引擎和編解碼
【雲棲號在線課堂】每天都有產品技術專家分享!
課程地址:https://yqh.aliyun.com/live立即加入社羣,與專家面對面,及時瞭解課程最新動態!
【雲棲號在線課堂 社羣】https://c.tb.cn/F3.Z8gvnK
原文發佈時間:2020-07-08
本文作者:edwardx
本文來自:“dockone”,瞭解相關信息可以關注“dockone”