初識 MQTT-爲什麼 MQTT 是最適合物聯網的網絡協議

原文鏈接:https://www.ibm.com/developerworks/cn/iot/iot-mqtt-why-good-for-iot/index.html

https://www.ibm.com/developerworks/cn/iot/iot-mqtt-why-good-for-iot/index.html

物聯網 (IoT) 設備必須連接互聯網。通過連接到互聯網,設備就能相互協作,以及與後端服務協同工作。互聯網的基礎網絡協議是 TCP/IP。MQTT(消息隊列遙測傳輸) 是基於 TCP/IP 協議棧而構建的,已成爲 IoT 通信的標準。

MQTT 最初由 IBM 於上世紀 90 年代晚期發明和開發。它最初的用途是將石油管道上的傳感器與衛星相鏈接。顧名思義,它是一種支持在各方之間異步通信的消息協議。異步消息協議在空間和時間上將消息發送者與接收者分離,因此可以在不可靠的網絡環境中進行擴展。雖然叫做消息隊列遙測傳輸,但它與消息隊列毫無關係,而是使用了一個發佈和訂閱的模型。在 2014 年末,它正式成爲了一種 OASIS 開放標準,而且在一些流行的編程語言中受到支持(通過使用多種開源實現)。

爲何選擇 MQTT

MQTT 是一種輕量級的、靈活的網絡協議,致力於爲 IoT 開發人員實現適當的平衡:

  • 這個輕量級協議可在嚴重受限的設備硬件和高延遲/帶寬有限的網絡上實現。
  • 它的靈活性使得爲 IoT 設備和服務的多樣化應用場景提供支持成爲可能。

爲了瞭解爲什麼 MQTT 如此適合 IoT 開發人員,我們首先來分析一下爲什麼其他流行網絡協議未在 IoT 中得到成功應用。

爲什麼不選擇其他衆多網絡協議

大多數開發人員已經熟悉 HTTP Web 服務。那麼爲什麼不讓 IoT 設備連接到 Web 服務?設備可採用 HTTP 請求的形式發送其數據,並採用 HTTP 響應的形式從系統接收更新。這種請求和響應模式存在一些嚴重的侷限性:

  • HTTP 是一種同步協議。客戶端需要等待服務器響應。Web 瀏覽器具有這樣的要求,但它的代價是犧牲了可伸縮性。在 IoT 領域,大量設備以及很可能不可靠或高延遲的網絡使得同步通信成爲問題。異步消息協議更適合 IoT 應用程序。傳感器發送讀數,讓網絡確定將其傳送到目標設備和服務的最佳路線和時間。
  • HTTP 是單向的。客戶端必須發起連接。在 IoT 應用程序中,設備或傳感器通常是客戶端,這意味着它們無法被動地接收來自網絡的命令。
  • HTTP 是一種 1-1 協議。客戶端發出請求,服務器進行響應。將消息傳送到網絡上的所有設備上,不但很困難,而且成本很高,而這是 IoT 應用程序中的一種常見使用情況。
  • HTTP 是一種有許多標頭和規則的重量級協議。它不適合受限的網絡。

出於上述原因,大部分高性能、可擴展的系統都使用異步消息總線來進行內部數據交換,而不使用 Web 服務。事實上,企業中間件系統中使用的最流行的消息協議被稱爲 AMQP(高級消息排隊協議)。但是,在高性能環境中,計算能力和網絡延遲通常不是問題。AMQP 致力於在企業應用程序中實現可靠性和互操作性。它擁有龐大的特性集,但不適合資源受限的 IoT 應用程序。

除了 AMQP 之外,還有其他流行的消息協議。例如,XMPP(Extensible Messaging and Presence Protocol,可擴展消息和狀態協議)是一種對等即時消息 (IM) 協議。它高度依賴於支持 IM 用例的特性,比如存在狀態和介質連接。與 MQTT 相比,它在設備和網絡上需要的資源都要多得多。

那麼,MQTT 爲什麼如此輕量且靈活?MQTT 協議的一個關鍵特性是發佈和訂閱模型。與所有消息協議一樣,它將數據的發佈者與使用者分離。

發佈和訂閱模型

MQTT 協議在網絡中定義了兩種實體類型:一個消息代理和一些客戶端。代理是一個服務器,它從客戶端接收所有消息,然後將這些消息路由到相關的目標客戶端。客戶端是能夠與代理交互來發送和接收消息的任何事物。客戶端可以是現場的 IoT 傳感器,或者是數據中心內處理 IoT 數據的應用程序。

  1. 客戶端連接到代理。它可以訂閱代理中的任何消息 “主題”。此連接可以是簡單的 TCP/IP 連接,也可以是用於發送敏感消息的加密 TLS 連接。
  2. 客戶端通過將消息和主題發送給代理,發佈某個主題範圍內的消息。
  3. 代理然後將消息轉發給所有訂閱該主題的客戶端。

因爲 MQTT 消息是按主題進行組織的,所以應用程序開發人員能靈活地指定某些客戶端只能與某些消息交互。例如,傳感器將在 “sensor_data” 主題範圍內發佈讀數,並訂閱 “config_change” 主題。將傳感器數據保存到後端數據庫中的數據處理應用程序會訂閱 “sensor_data” 主題。管理控制檯應用程序能接收系統管理員的命令來調整傳感器的配置,比如靈敏度和採樣頻率,並將這些更改發佈到 “config_change” 主題。(參閱圖 1。)

圖 1. IoT 傳感器的 MQTT 發佈和訂閱模型

使用 MQTT 代理、數據存儲和管理控制檯發佈和訂閱傳感器數據消息的流程圖

點擊查看大圖

同時,MQTT 是輕量級的。它有一個用來指定消息類型的簡單標頭,有一個基於文本的主題,還有一個任意的二進制有效負載。應用程序可對有效負載採用任何數據格式,比如 JSON、XML、加密二進制或 Base64,只要目標客戶端能夠解析該有效負載。

MQTT 開發入門

開始進行 MQTT 開發的最簡單工具是 Python mosquitto 模塊,該模塊包含在 Eclipse Paho 項目 中,提供了多種編程語言格式的 MQTT SDK 和庫。它包含一個能在本地計算機上運行的 MQTT 代理,還包含使用消息與代理交互的命令行工具。可以從 mosquitto 網站 下載並安裝 mosquitto 模塊。

mosquitto 命令在本地計算機上運行 MQTT 代理。也可以使用 -d 選項在後臺運行它。

$ mosquitto -d

接下來,在另一個終端窗口中,可以使用 mosquitto_sub 命令連接到本地代理並訂閱一個主題。運行該命令後,它將等待從訂閱的主題接收消息,並打印出所有消息。

$ mosquitto_sub -t "dw/demo"

在另一個終端窗口中,可以使用 mosquitto_pub 命令連接到本地代理,然後向一個主題發佈一條消息。

$ mosquitto_pub -t "dw/demo" -m "hello world!"

現在,運行 mosquitto_sub 的終端會在屏幕上打印出 “hello world!”。您剛纔使用 MQTT 代理髮送並接收了一條消息!

當然,在生產系統中,不能使用本地計算機作爲代理。相反,可以使用 IBM Bluemix Internet of Things Platform 服務,這是一種可靠的按需服務,功能與 MQTT 代理類似。要進一步瞭解這個 Bluemix 服務如何集成並使用 MQTT 作爲與設備和應用程序通信的協議,請參閱 該服務的文檔。)

IBM Bluemix Internet of Things Platform 服務 的工作原理如下。

  • 從 Bluemix 控制檯,可以在需要時創建 Internet of Things Platform 服務的實例。
  • 然後,可以添加能使用 MQTT 連接該服務實例的設備。每個設備有一個 ID 和名稱。只有列出的設備能訪問該服務,Watson IoT Platform 儀表板會報告這些設備上的流量和使用信息。
  • 對於每個設備客戶端,Bluemix 會分配一個主機名、用戶名和密碼,用於連接到您的服務實例(MQTT 代理)。(在 Bluemix 上,用戶名始終爲 use-token-auth,密碼始終是圖 2 中顯示的每個連接設備的令牌。)

圖 2. 在 IBM Bluemix 中創建 Internet of Things Platform 服務

點擊查看大圖

使用遠程 MQTT 代理時,需要將代理的主機名和身份驗證憑證傳遞給 mosquitto_sub 和 mosquitto_pub 命令。例如,下面的命令使用了 Bluemix 提供的用戶名和密碼,訂閱我們的 Internet of Things Platform 服務上的 demo 主題:

$ mosquitto_sub -t "demo" -h host.iotp.mqtt.bluemix.com -u username -P password

有關使用 mosquitto 工具的更多選擇,以及如何使用 mosquitto API 創建自己的 MQTT 客戶端應用程序,請參閱 mosquitto 網站 上的文檔。

有了必要的工具後,讓我們來更深入地研究 MQTT 協議。

瞭解 MQTT 協議

MQTT 是一種連接協議,它指定了如何組織數據字節並通過 TCP/IP 網絡傳輸它們。但實際上,開發人員並不需要了解這個連接協議。我們只需要知道,每條消息有一個命令和數據有效負載。該命令定義消息類型(例如 CONNECT 消息或 SUBSCRIBE 消息)。所有 MQTT 庫和工具都提供了直接處理這些消息的簡單方法,並能自動填充一些必需的字段,比如消息和客戶端 ID。

首先,客戶端發送一條 CONNECT 消息來連接代理。CONNECT 消息要求建立從客戶端到代理的連接。CONNECT 消息包含以下內容參數。

表 1. CONNECT 消息參數

參數 說明
cleanSession 此標誌指定連接是否是持久性的。持久會話會將所有訂閱和可能丟失的消息(具體取決於 QoS) 都存儲在代理中。(請參閱 表 3 獲取 QoS 的描述。)
username 代理的身份驗證和授權憑證。
password 代理的身份驗證和授權憑證。
lastWillTopic 連接意外中斷時,代理會自動向某個主題發送一條 “last will” 消息。
lastWillQos “last will” 消息的 QoS。(請參閱 表 3 來查看 QoS 的描述。)
lastWillMessage “last will” 消息本身。
keepAlive 這是客戶端通過 ping 代理來保持連接有效所需的時間間隔。

客戶端收到來自代理的一條 CONNACK 消息。CONNACK 消息包含以下內容參數。

表 2. CONNACK 消息參數

參數 說明
sessionPresent 此參數表明連接是否已有一個持久會話。也就是說,連接已訂閱了主題,而且會接收丟失的消息。
returnCode 0 表示成功。其他值指出了失敗的原因。

建立連接後,客戶端然後會向代理髮送一條或多條 SUBSCRIBE 消息,表明它會從代理接收針對某些主題的消息。消息可以包含一個或多個重複的參數。如表 3。

表 3. SUBSCRIBE 消息參數

參數 說明
qos qos(服務質量或 QoS)標誌表明此主題範圍內的消息傳送到客戶端所需的一致程度。 
  • 值 0:不可靠,消息基本上僅傳送一次,如果當時客戶端不可用,則會丟失該消息。
  • 值 1:消息應傳送至少 1 次。
  • 值 2:消息僅傳送一次。
topic 要訂閱的主題。一個主題可以有多個級別,級別之間用斜槓字符分隔。例如,“dw/demo” 和 “ibm/bluemix/mqtt” 是有效的主題。

客戶端成功訂閱某個主題後,代理會返回一條 SUBACK 消息,其中包含一個或多個 returnCode 參數。

表 4. SUBACK 消息參數

參數 說明
returnCode SUBCRIBE 命令中的每個主題都有一個返回代碼。返回值如下所示。 
  • 值 0 - 2:成功達到相應的 QoS 級別。(參閱 表 3 進一步瞭解 QoS。)
  • 值 128:失敗。

與 SUBSCRIBE 消息對應,客戶端也可以通過 UNSUBSCRIBE 消息取消訂閱一個或多個主題。

表 5. UNSUBSCRIBE 消息參數

參數 說明
topic 此參數可重複用於多個主題。

客戶端可向代理髮送 PUBLISH 消息。該消息包含一個主題和數據有效負載。代理然後將消息轉發給所有訂閱該主題的客戶端。

表 6. PUBLISH 消息參數

參數 說明
topicName 發佈的消息的相關主題。
qos 消息傳遞的服務質量水平。(請參閱 表 3 來查看 QoS 的描述。)
retainFlag 此標誌表明代理是否保留該消息作爲針對此主題的最後一條已知消息。
payload 消息中的實際數據。它可以是文本字符串或二進制大對象數據。

技巧和解決方法

MQTT 的優勢在於它的簡單性。在可以使用的主題類型或消息有效負載上沒有任何限制。這支持一些有趣的用例。例如,請考慮以下問題:

如何使用 MQTT 發送 1-1 消息?雙方可以協商使用一個特定於它們的主題。例如,主題名稱可以包含兩個客戶端的 ID,以確保它的唯一性。

客戶端如何傳輸它的存在狀態?系統可以爲 “presence” 主題協商一個命名約定。例如,“presence/client-id” 主題可以擁有客戶端的存在狀態信息。當客戶端建立連接時,將該消息被設置爲 true,在斷開連接時,該消息被設置爲 false。客戶端也可以將一條 last will 消息設置爲 false,以便在連接丟失時設置該消息。代理可以保留該消息,讓新客戶端能夠讀取該主題並找到存在狀態。

如何保護通信?客戶端與代理的連接可以採用加密 TLS 連接,以保護傳輸中的數據。此外,因爲 MQTT 協議對有效負載數據格式沒有任何限制,所以系統可以協商一種加密方法和密鑰更新機制。在這之後,有效負載中的所有內容可以是實際 JSON 或 XML 消息的加密二進制數據。

結束語

本文從技術角度介紹了 MQTT 協議。您瞭解了 MQTT 是什麼,MQTT 爲什麼適合 IoT 應用程序,以及如何開始開發使用 MQTT 的應用程序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章