MQTT 協議快速體驗

語言: CN / TW / HK

全球物聯網正在高速發展,專門針對低頻寬和不穩定網路環境的物聯網應用設計的 MQTT 協議也因此得到廣泛應用。

MQTT 是一種基於釋出/訂閱模式輕量級訊息傳輸協議,具有簡單易實現、支援 QoS、報文小等特點,非常適用於工業網際網路、車聯網、智慧硬體、電力能源等領域。

本文將通過講解與演示向讀者展示 MQTT 協議的入門使用流程,物聯網及 MQTT 初學者可以通過本文以更簡單的方式理解 MQTT 相關概念,快速開始 MQTT 服務及應用的開發。

MQTT 連線

在使用 MQTT 協議進行通訊之前,需要先建立一個 MQTT 連線,連線由客戶端向伺服器端發起。

MQTT 客戶端

任何運行了 MQTT 客戶端庫的程式或裝置都是一個 MQTT 客戶端,例如:使用了 MQTT 的即時通訊 APP 是一個客戶端,使用 MQTT 上報資料的各種感測器裝置是一個客戶端,以及各種 MQTT 測試工具也是一個客戶端。

目前,基本所有的程式語言都有成熟的開源 MQTT 客戶端庫,讀者可參考 EMQ 整理的 MQTT 客戶端庫大全選擇一個合適的客戶端庫來構建滿足自身業務需求的 MQTT 客戶端。也可直接訪問 EMQ 提供的 MQTT 客戶端程式設計系列部落格,學習如何在 Java、Python、PHP、Node.js 等程式語言中使用 MQTT。

本次演示我們將使用由 MQTT X 提供的支援瀏覽器訪問的線上 MQTT 客戶端:http://www.emqx.io/online-mqtt-client。MQTT X 是目前開源客戶端中 GitHub Star 數最多的,它同時也提供了桌面客戶端(http://mqttx.app/zh)與命令列客戶端(http://mqttx.app/zh/cli),感興趣的讀者可自行下載使用。

MQTT 伺服器

MQTT 伺服器負責接收客戶端發起的連線,並將客戶端傳送的訊息轉發到另外一些符合條件的客戶端。一個成熟的 MQTT 伺服器可支援海量的客戶端連線及百萬級的訊息吞吐,幫助物聯網業務提供商專注於業務功能並快速建立一個可靠的 MQTT 應用。

MQTT 伺服器一般有私有部署、全託管雲服務、公共線上三種形式。

  • 私有部署需要自行搭建與維護伺服器,適合接入量較大、且有技術團隊支援的公司。

讀者若是希望搭建私有 MQTT 伺服器進行測試,可執行如下 Docker 命令直接安裝 EMQX 開源版。

apache docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx

也可參考部落格如何在 Ubuntu 上安裝 EMQX MQTT 伺服器進行安裝。

  • 全託管雲服務免除了企業維護基礎設施的負擔,簡單幾步就能輕鬆開啟 MQTT 服務。如下圖,EMQX Cloud 支援按連線建立 MQTT 服務,且可選擇部署在多個雲平臺。

MQTT Cloud 圖1.png

  • 公共的線上伺服器一般由各個 MQTT 伺服器的所屬商業公司所提供,主要用來做 MQTT 流程測試。

本次演示我們將使用由 EMQ 提供的公共 MQTT 伺服器,該伺服器基於全託管的 MQTT 雲服務 - EMQX Cloud 建立,伺服器資訊如下:

  • Broker: broker.emqx.io
  • TCP Port: 1883
  • Websocket Port: 8083

建立連線

接下來我們開始正式建立一個 MQTT 連線,使用瀏覽器訪問 http://www.emqx.io/online-mqtt-client,然後點選頁面中間的 New Connection 按鈕,將會看到如下頁面。

建立 MQTT 連線 圖2.png

各個連線的引數的意義如下:

  • Name:為該線上客戶端特有,只是一個區分不同連線的名稱,與連線的建立無關係。使用程式碼連線時沒有該引數。
  • Client ID:服務端使用 Client ID 識別客戶端,連線服務端的每個客戶端都必須要有唯一的 Client ID。
  • Host:為連線的伺服器地址及協議,協議一般有 4 種:基於普通 TCP 的 MQTT、基於 SSL/TLS 的 MQTT、基於 WebSocket 的 MQTT,基於加密 WebSocket 的 MQTT。本文使用的線上工具基於瀏覽器執行,所以只能選擇 ws 或 wss 協議。
  • Port:連線的伺服器埠。
  • Path:選 ws 或 wss 協議時需要填寫,EMQX 伺服器預設為 /mqtt
  • Username,Password:MQTT 可以通過傳送使用者名稱和密碼來進行相關的認證和授權,但是,如果此資訊未加密,則使用者名稱和密碼是以明文的方式傳送的。
  • Connect Timeout:連線超時時間,連線在多少秒內未成功則不再繼續連線。
  • Keep Alive:保活週期,是一個以秒為單位的時間間隔。客戶端在無報文傳送時,將按 Keep Alive 設定的值定時向服務端傳送心跳報文,確保連線不被服務端斷開。更多細節可檢視部落格:MQTT 協議中的 Keep Alive 機制
  • Clean Session:清除會話,為 false 時表示建立一個持久會話,在客戶端斷開連線時,會話仍然保持並儲存離線訊息,直到會話超時登出。否則表示建立一個新的臨時會話,在客戶端斷開時,會話自動銷燬。
  • Auto Reconnect:自動重連,幾乎所有客戶端庫都實現了自動重連。如果設定了自動重連,當網路不佳連線被斷開後,客戶端將自動重新發起連線。
  • MQTT Version:MQTT 版本,建議使用 5.0。MQTT 5.0 是為適應迅速增長的裝置數量與企業需求而全面更新的一個版本,其在 3.1.1 版本基礎上增加了會話/訊息延時、原因碼、主題別名、使用者屬性、共享訂閱等更加符合現代物聯網應用需求的特性。更多 MQTT 5.0 詳細資訊可檢視 EMQ 提供的 MQTT 5.0 專題系列文章。

我們在 Name 裡輸入 Simple Demo,並點選右上角的 Connect 按鈕即可建立一個 MQTT 連線,如下表示連線建立成功。

MQTT 連線成功 圖3.png

釋出與訂閱

連線成功後,客戶端就能進行訊息的收發,在訊息收發前我們需要先理解發布/訂閱模式。

釋出/訂閱模式

釋出訂閱模式區別於傳統的客戶端-伺服器模式,它使傳送訊息的客戶端(釋出者)與接收訊息的客戶端(訂閱者)分離,釋出者與訂閱者不需要建立直接聯絡。我們既可以讓多個釋出者向一個訂閱者釋出訊息,也可以讓多個訂閱者同時接收一個釋出者的訊息,它的精髓在於由一個被稱為代理(MQTT 伺服器)的中間角色負責所有訊息路由和分發的工作。

下圖為 MQTT 的釋出/訂閱流程:溫度感測器作為一個客戶端連線至 MQTT 伺服器後,即可向某個主題(比如 Temperature)釋出溫度訊息,伺服器收到該訊息後會將訊息轉發至訂閱了 Temperature 主題的客戶端(比如下圖的手機、瀏覽器等應用)。

釋出訂閱模式圖4.png

主題(Topic)

MQTT 協議基於主題進行訊息路由,主題類似 URL 路徑,例如:

```awk chat/room/1

sensor/10/temperature

sensor/+/temperature ```

主題通過 / 分割層級,支援 +# 萬用字元:

  • +:表示通配一個層級,例如 a/+ 匹配 a/xa/y
  • #:表示通配多個層級,例如 a/# 匹配 a/xa/b/c/d

更多關於 MQTT 主題的介紹可檢視部落格:MQTT 主題的高階特性

訊息服務質量(QoS)

MQTT 協議提供了 3 種訊息服務質量等級(Quality of Service),它保證了在不同的網路環境下訊息傳遞的可靠性。

  • QoS 0:訊息最多傳遞一次。

如果當時客戶端不可用,則會丟失該訊息。釋出者傳送一條訊息之後,就不再關心它有沒有傳送到對方,也不設定任何重發機制。

  • QoS 1:訊息傳遞至少 1 次。

包含了簡單的重發機制,釋出者傳送訊息之後等待接收者的 ACK,如果沒收到 ACK 則重新發送訊息。這種模式能保證訊息至少能到達一次,但無法保證訊息重複。

  • QoS 2:訊息僅傳送一次。

設計了重發和重複訊息發現機制,保證訊息到達對方並且嚴格只到達一次。

更多關於 MQTT QoS 的介紹可檢視部落格:MQTT QoS 服務質量介紹

訂閱主題

接下來我們模擬溫度感測器場景,在之前建立的 Simple Demo 連線裡訂閱所有的溫度感測器上報的溫度資料,即訂閱萬用字元主題 sensor/+/temperature

如下圖,點選按鈕 New Subscription,在彈出框的 Topic 下面輸入主題 sensor/+/temperature,QoS 保持預設 0 不變。

Color 欄位可修改訂閱標籤的顏色,Alias 欄位可修改訂閱主題的顯示名稱。這兩個欄位為該線上客戶端特有,使用程式碼連線時無此引數。

訂閱 MQTT 主題 圖5.png

訂閱成功後即可看到中間的訂閱列表裡多了一條記錄。

主題訂閱成功 圖6.png

釋出訊息

接下來我們點選最左側的 + 按鈕分別建立 Sensor 1Sensor 2 兩個連線,模擬兩個溫度感測器。

建立 MQTT 連線 圖7.png

連線建立好後如下圖所示,將會看到 3 個連線,並且連線左側的線上狀態圓點都為綠色(綠色說明連線成功)。

連線建立成功 圖8.png

選中 Sensor 1 連線,在頁面右下部分輸入釋出主題 sensor/1/temperature,訊息框內輸入如下 JSON 格式訊息,並點選右側最底部的釋出按鈕傳送訊息。

json { "msg": "17.2" }

釋出 MQTT 訊息 圖9.png

如下表示訊息傳送成功。

訊息釋出成功 圖10.png

使用同樣的步驟,在 Sensor 2 連線裡向 sensor/2/temperature 主題釋出如下 JSON 訊息。

json { "msg": "18.2" }

將會看到 Simple Demo 連線收到 2 條新訊息。

訊息通知 圖11.png

點選 Simple Demo 連線,將會看到兩個感測器傳送的兩條訊息。

收到兩條 MQTT 訊息 圖12.png

MQTT 重要特性演示

保留訊息(Retained Message)

MQTT 客戶端向伺服器釋出訊息時,可以設定保留訊息標誌。一個主題下最新一條保留訊息會駐留在訊息伺服器,後來的訂閱者訂閱主題時仍可以接收該訊息。

如下圖,我們在 Sensor 1 連線裡向 retained_message 主題傳送兩條不一樣的訊息,且傳送訊息時勾選 Retain 選項。

MQTT 保留訊息 圖13.png

然後,我們再在 Simple Demo 連線裡訂閱 retained_message 主題,訂閱成功後將會收到 Sensor 1 傳送的第二條保留訊息,由此可見伺服器只會儲存一個主題下最後一條保留訊息。

MQTT 保留訊息 圖14.png

清除會話(Clean Session)

一般情況下 MQTT 客戶端僅能接收到線上時其他客戶端釋出的訊息,如果客戶端離線再上線後將收不到離線期間的訊息。但是當客戶端使用固定的 Client ID,且連線引數 Clean Session 為 false 時,客戶端離線後訊息伺服器可以為客戶端保持一定量的離線訊息,並在客戶端再次上線後傳送給客戶端(且為客戶端恢復下線前的訂閱資訊)。

本次演示使用的公共 MQTT 伺服器設定的離線訊息儲存時間為 5 分鐘,最大訊息數為 1000 條,且不儲存 QoS 0 訊息。接下來我們建立一個 MQTT 3.1.1 版本的連線,並驗證 QoS 1 情況下的離線會話。

MQTT 5 中使用 Clean Start 與 Session Expiry Interval 改進了 Clean Session,詳情可檢視部落格:Clean Start 與 Session Expiry Interval

如下圖,建立一個名為 MQTT V3 的連線,Clean Session 設定為 false,MQTT 版本選擇 3.1.1。

MQTT 清除會話 圖15.png

連線成功後訂閱 clean_session_false 主題,且 QoS 設定為 1。

訂閱 MQTT 主題 圖16.png

訂閱成功後,點選右上角的斷開連線按鈕。

斷開 MQTT 連線 圖17.png

接下來建立一個名為 MQTT_V3_Publish 的連線,MQTT 版本同樣設定為 3.1.1,連線成功後向 clean_session_false 主題釋出三條訊息。

釋出 MQTT 訊息 圖18.png

然後選中 MQTT_V3 連線,點選連線按鈕連線至伺服器,將會成功接收到 3 條離線期間的訊息。

MQTT 離線訊息 圖19.png

遺囑訊息(Last Will)

MQTT 客戶端向伺服器發起連線請求時,可以設定是否傳送遺囑訊息(Will Message)標誌,和遺囑訊息主題(Topic)與內容(Payload)。設定了遺囑訊息訊息的 MQTT 客戶端異常下線時(客戶端斷開前未向伺服器傳送 DISCONNECT 訊息),MQTT 訊息伺服器會發布該客戶端設定的遺囑訊息。

更多關於遺囑訊息的介紹可檢視部落格:MQTT 遺囑訊息(Will Message)的使用

如下圖,我們建立一個名為 Last Will 的連線。

  • 為了能快速看到效果,我們設定 Keep Alive 為 5 秒
  • Last-Will Topic 設定為 last_will
  • Last-Will QoS 設定為 1
  • Last-Will Retain 設定為 true
  • Last-Will Payload 設定為 offline

MQTT 遺囑訊息 圖20.png

連線成功後,我們斷開電腦網路 5 秒鐘以上(模擬客戶端異常下線),再開啟網路。然後啟動 Simple Demo 連線,並訂閱 last_will 主題,將會收到 Last Will 連線設定的遺囑訊息。

MQTT 遺囑訊息 圖21.png

至此,我們完成了對 MQTT 相關基礎概念及其使用流程的講解與演示,讀者可以根據本文所學嘗試上手使用 MQTT 協議。接下來讀者可訪問 EMQ 提供的 MQTT 客戶端程式設計系列部落格,學習如何在 Java、Python、PHP、Node.js 等程式語言中使用 MQTT,開始 MQTT 應用及服務開發,探索 MQTT 的更多高階應用。

版權宣告: 本文為 EMQ 原創,轉載請註明出處。

原文連結:http://www.emqx.com/zh/blog/the-easiest-guide-to-getting-started-with-mqtt