MQTT 協議是什么

隨著 5G 時代的來臨,萬物物聯的偉大構想正在成為現實。聯網的物聯網設備在 2018 年已經達到了 70 億[1],在未來兩年,僅智能水電氣表就將超過10億[2]。

image

海量的設備接入和設備管理對網絡帶寬、通信協議以及平臺服務架構都帶來了很大挑戰。對于物聯網協議來說,必須針對性地解決物聯網設備通信的幾個關鍵問題:其網絡環境復雜而不可靠、其內存和閃存容量小、其處理器能力有限。

MQTT 是基于 Publish/Subscribe 模式的物聯網通信協議,憑借簡單易實現、支持 QoS、報文小等特點,占據了物聯網協議的半壁江山:

image

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, 注意 MQTT之間的空格,其全稱為: 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 的訂閱者:

image

上圖中訂閱者預先訂閱了 news,然后發布者向 Broker 發布了一條消息 "some msg" 并制定發布到 news 主題,Broker 通過 Topic 匹配,決定將這條消息轉發給訂閱者。

MQTT 的 Topic 有層級結構,并且支持通配符 +#:

  • + 是匹配單層的通配符。比如 news/+ 可以匹配 news/sportsnews/+/basketball 可匹配到 news/sports/basketball。
  • # 是一到多層的通配符。比如 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 的?;顧C制[3],而是設計了協議層的保活機制:在 CONNECT 報文里可設置 Keepalive 字段,來設置保活心跳包 PINGREQ/PINGRESP 的發送時間間隔。當長時間無法收到設備的 PINGREQ 的時候,Broker 就會認為設備已經下線。

總的來說,Keepalive 有兩個作用:

  • 發現對端死亡或者網絡中斷
  • 在長時間無消息交互的情況下,保持連接不被網絡設備斷開

對于那些想要在重新上線后,重新收到離線期間錯過的消息的設備,MQTT 設計了持久化連接:在 CONNECT 報文里可設置 CleanSession 字段為 False,則 Broker 會為終端存儲:

  • 設備所有的訂閱
  • 還未被設備確認的 QoS1 和 QoS 消息
  • 設備離線時錯過的消息

在線狀態感知

MQTT 設計了遺愿(Last Will) 消息,讓 Broker 在發現設備異常下線的情況下,幫助設備發布一條遺愿消息到指定的主題。

實際上在某些 MQTT Broker 的實現里 (比如 EMQX),設備上線或下線的時候 Broker 會通過某些系統主題發布設備狀態更新,更符合實際應用場景。

開源 MQTT Broker 如何選擇

到目前為止,比較流行的 MQTT Broker 有幾個:

  1. Eclipse Mosquitto: https://github.com/eclipse/mosquitto

    使用 C 語言實現的 MQTT Broker。Eclipse 組織還還包含了大量的 MQTT 客戶端項目:https://www.eclipse.org/paho/#

  2. EMQX: https://github.com/emqx/emqx

    使用 Erlang 語言開發的 MQTT Broker,支持許多其他 IoT 協議比如 CoAP、LwM2M 等

  3. Mosca: https://github.com/mcollina/mosca

    使用 Node.JS 開發的 MQTT Broker,簡單易用。

  4. VerneMQ: https://github.com/vernemq/vernemq

    同樣使用 Erlang 開發的 MQTT Broker

從支持 MQTT5.0、穩定性、擴展性、集群能力等方面考慮,EMQX 的表現應該是最好的:

  • 使用 Erlang OTP 開發,容錯能力好 (電信領域久經考驗的語言,曾經做出過 99.9999999% 可用性的交換機設備[4])
  • 官方有大量的擴展插件可供擴展。有很多認證插件,數據存儲(backend)插件可供選擇。可支持各種關系型數據庫,NoSQL 數據庫,以及常見消息隊列如 Kafka,RabbitMQ,Pulsar 等
  • 支持集群,支持節點水平擴展
  • 單節點支持 2000K 并發連接
  • 支持規則引擎和編解碼

作者:EMQ
鏈接:http://www.lxweimin.com/p/32f81eb15d29

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372