MQTT,弱網之友

背景

 最近搭建私有云環境中使用了 MQTT,MQTT 作爲客戶端和服務端之之間的長連接中間件,主要用作客戶端和服務端之間的信息交換。順手寫個文章分享一下。

介紹

什麼是 MQTT

 首先 MQTT 不是 MQ(消息隊列),只是名字帶有 MQ。

 MQTT(Message Queuing Telemetry Transport),一種基於發佈 / 訂閱模式的消息傳輸協議,它設計輕巧、易於實現,非常適合需要低帶寬、高延遲或不可靠網絡的應用場景,基於 TCP/IP 協議建立。

架構

 從架構圖可以看出,基於 發佈 / 訂閱 模式的的 MQTT 架構是比較簡單的。

 設備(客戶端,比如溫度傳感器)發佈消息(比如 溫度)到特定的主題,而其他感興趣的設備(訂閱者,比如警報系統)可以訂閱這些主題以接收消息。這種模式解耦了消息的發佈者和訂閱者,使得系統更加靈活和可擴展。

一些術語

Broker

 MQTT Broker 是 MQTT 系統中的中間件,負責接收來自發布者的報文,處理這些報文,並將其分發給訂閱相應主題的訂閱者。

 Broker 是消息路由和分發的核心。

 MQTT Broker 一般只負責消息轉發,不存儲信息。可以將 MQTT Broker 理解爲郵局,將收到的信件(消息)進行分類(主題)並轉發給對應的人(訂閱者)。

主題(Topic)

 MQTT 使用主題來區分消息的類型。主題是一個字符串,用於匹配發布者和訂閱者之間的消息。

 主題可以包含層次結構,類似於文件系統的路徑,例如 “wushihong/topic/1”。

發佈者(Publisher)

 發佈者是發送消息到 MQTT 主題的客戶端。它可以發送不同服務質量(QoS)等級的消息。

訂閱者(Subscriber)

 訂閱者是接收特定主題消息的客戶端。訂閱者指定它感興趣的主題,並接收來自這些主題的消息。

關鍵內容

服務質量

MQTT 提供了三個級別的服務質量(QoS):

消息類型

MQTT 定義了幾種不同類型的控制報文,包括:

下面通過使用演示

保留標誌

 MQTT 的 PUBLISH 報文中的保留標誌(Retain Flag)用於指示服務器在消息被髮送後,是否應該保留這條消息,並將其轉發給後續的訂閱者。

 如果保留標誌被設置,服務器會存儲這條消息,並將其發送給所有新訂閱該主題的客戶端,直到一條新的帶有保留標誌的消息被髮布,或者服務器端的保留消息被顯式刪除。

 保留消息通常用於發送者向所有當前和未來的訂閱者廣播消息,例如,設備的當前狀態或告警信息。

爲什麼要用 MQTT

區別於 MQ

整合於 MQ

一般情況下,MQTT 可以 和 MQ 結合使用,MQTT 可以作爲消息的接入協議,而 MQ 系統可以作爲後端處理消息的隊列系統。

遇到過的問題

 本次我使用的 MQTT Broker 是經過二次開發的,支持配置單個客戶端單個主題的單位時間內發送消息條數,開發過程有同事修改了配置導致訂閱者收不到消息。

 發行版的 EMQX 也有相關配置,可以限制單個客戶端的發佈速率。

 而 MQTT 5.0 有類似配置 Receive Maximum,用於告知 Broker 客戶端願意接收的最大消息數。雖然這不是直接限制發送速率,但它可以幫助調整客戶端和 Broker 之間的消息流量。

 由於我們的客戶端需要在斷連後加入業務,因此沒有直接使用 SDK 的自動重連。但是也帶來了一些問題,比如重連的觸發時間、重試間隔、連接狀態記錄等都需要注意。

 所以如果沒有特殊的業務要求可以直接使用 SDK 的自動重連,只需要實現 SDK 中斷連的回調函數即可簡單處理斷連後觸發的業務。

 考慮到客戶端斷網狀態下的消息丟失,客戶端在連接時必須設置cleanSession false(不清理 session),並且 Broker 需要支持消息持久化功能。

設置cleanSessionfalse,Broker 就會保留客戶端的訂閱信息和未發送的消息,客戶端在重新連接後可以繼續接收之前訂閱的主題的消息。

而 Broker 消息持久化,可以通過設置persistence true來啓用。

部署演示

win 環境,本地部署

1、下載 mosquitto 並安裝

2、修改 mosquitto.conf

# 1、端口
#listener
listener 1883

# 2、方便演示 允許匿名登錄
allow_anonymous = true

3、啓動

.\mosquitto -c mosquitto.conf

4、爲了直觀演示主題訂閱、消息發送、和消息接收,這裏使用 MQTTX 可是化客戶端演示

可視化客戶端演示

5、爲了觀察過程,這裏用命令行再演示一次 主題訂閱、消息發送、消息接收

5.1、 QoS 0

訂閱和發佈

# -d 開啓debug消息
# -v 打印更多的調試信息
# -t 指定主題,此處爲 wushihong/topic/1
# --QoS 設置QoS,默認0
.\mosquitto_sub -v -t wushihong/topic/1

# -d 開啓debug消息
# -t 指定主題,此處爲 wushihong/topic/1
# -m 發佈的消息內容,此處爲 helloworld
# --QoS 設置QoS,默認0
.\mosquitto_pub -d -t wushihong/topic/1 -m 'helloworld'

 可以看到客戶端和服務端一些報文,有 CONNECT、CONNACK、SUBSCRIBE、PUBLISH 等不一一列舉,可以參考上面的報文類型解釋。

5.3、使用 QoS 1 發佈消息

 QoS 2 的發佈者和訂閱者都多了比上面 QoS 1 的多了 PUBACK 報文。

5.4、使用 QoS 2 發佈消息

 QoS 2 比 QoS 1 多了 3 個報文,分別是 PUBREC(發佈消息接收)、PUBREL(發佈消息釋放) 和 PUBCOMP(發佈消息完成)。其中 m1 指的是消息 ID,rc0 表示沒有錯誤(return code 0)。

 其實就是一個握手的過程,篇幅有限不一一解釋。

需要注意的是,訂閱者和發佈者的 QoS 不一致時,訂閱者接收消息會以兩者中取最小值 QoS

集羣

 生產環境一般都需要集羣部署,不會採用上面演示的單節點的方式。

 使用 MQTT Broker 集羣的主要優勢在於它能夠提供高可擴展性、高可用性、負載均衡、集中管理和靈活的維護能力。

 MQTT Broker 集羣有多種實現方式,比如 分佈式集羣架構、主從集羣架構、橋接集羣架構等,每種架構都有其特定的優勢和適用場景,選擇合適的集羣架構取決於具體的業務需求和預期的負載。

    例如,對於需要高併發連接和高吞吐量的場景,分佈式集羣架構可能是最合適的選擇。而對於需要高可用性和故障轉移能力的場景,主從集羣架構可能更合適。

最後

 總的來說,MQTT 很適合低帶寬、高延遲或不可靠網絡的應用場景。

 我們本次部署針對局域網內的,不過現在物聯網越來越普遍,部署在公網的 MQTT broker 非常常見,現在各大雲廠商也都有 MQTT 的雲服務,安全性也來越好。所以後續應該也會考慮上雲。

參考: 

MQTT: https://MQTT.org/

mosquitto: https://mosquitto.org/

emqx: https://www.emqx.com/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/3swGV9waey6LJoIgRh1EQQ