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 數最多的,它同時也提供了桌面客户端(https://mqttx.app/zh)與命令行客户端(https://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 原創,轉載請註明出處。

原文鏈接:https://www.emqx.com/zh/blog/the-easiest-guide-to-getting-started-with-mqtt