MQTT 通信的核心:Topic 主題
我們這期重點介紹 MQTT 的靈活性和效率的核心,即兩個關鍵概念:主題 Topic 和通配符 Wildcards。這些功能構成了 MQTT 發佈 / 訂閱模型的基礎,使得在複雜的物聯網生態系統中實現無縫且有針對性的通信成爲可能。
MQTT 主題作爲消息的地址機制,允許設備和應用程序組織和過濾信息流。它們提供了一種層次結構,可以表示您的物聯網系統中的各種方面,從設備位置到傳感器類型和數據類別。瞭解如何有效地設計和利用主題對於創建可擴展且易於管理的物聯網解決方案至關重要。
與主題互補的是 MQTT 通配符,這些強大的工具增強了協議的靈活性。通配符允許訂閱者同時從多個主題接收消息,簡化客戶端邏輯並減少網絡開銷。通過掌握通配符,開發人員可以創建更動態和響應式的物聯網應用,能夠適應不斷變化的數據需求而無需不斷重新配置。
接下來我們將深入探討 MQTT 主題和通配符的複雜性,探索它們的結構、最佳實踐和高級功能。
什麼是 Topic 主題?
Topic 主題指的是一個 UTF-8 字符串,用於過濾連接客戶端的消息。主題由一個或多個級別組成,級別之間用正斜槓分隔(主題級別分隔符)。以下是如何爲家中辦公室的燈創建一個主題的例子:
需要注意的是:主題是區分大小寫的,因此這兩個主題是不同的:
如果您想通過 MQTT 在家庭辦公室中打開一盞燈,可以想象以下場景:
-
一個設備在 home/office/lamp 主題上發佈 “on” 和“off”消息。您有一個控制燈的設備(可以是 ESP32、ESP8266 或其他任何板子或設備)。
-
控制您燈的 ESP32 訂閱了相同的主題:home/office/lamp。
-
因此,當該主題發佈新消息時,ESP32 會接收到 “開” 或“關”消息並控制燈的開關。
使用 Topic 最佳的實踐指南
以下最佳實踐支持創建一個清晰結構化的 MQTT 主題層次結構,這是可擴展的工業統一命名空間(UNS)架構的基礎。
確保清晰
明確的主題對於確保 MQTT 客戶端和代理之間的順暢數據傳輸至關重要。清晰且無歧義的主題命名可以防止衝突並促進工業生態系統內的順暢互操作性。注意:MQTT 主題是區分大小寫的。這意味着 x/y
和 X/y
被視爲兩個不同的主題。
工廠之間的標準化
整個公司的主題結構需要保持一致。這種結構應該適用於所有設施、生產線和機器。同時,可以通過引入專門用於特殊用例的主題來考慮不同組織層級的個別需求,例如 e``nterprise/site/area/workCell/individual
。
粒度 vs. 模塊化
在粒度和模塊化之間取得良好的平衡至關重要。粒度或模塊化的決策應基於您的用例需求。
-
粒度使個體數據點的詳細映射成爲可能,例如在特定主題
.../temperature
中的溫度值。這使得以有針對性的方式訂閱特定事件和數據變得更加容易。 -
模塊化將多個數據點組合到一個共同的主題中,這支持了 MQTT 命名空間的清晰性和可擴展性。例如,所有傳感器數據,如溫度、壓力和溼度,可以一起發佈到
.../sensor
主題中。
分層組織
主題結構應反映一個明確定義的層次結構,該層次結構反映了您的工業生態系統中的物理和邏輯結構。主題的樹狀組織使得可以在較高層次放置更廣泛的類別(例如 “工廠” 或“生產線”),並在其下方放置更具體的主題(例如 “訂單” 或“傳感器數據”)。這提供了幾個優勢:
-
清晰度:良好的結構化層次使得在 MQTT 命名空間中理解和導航更加容易。
-
靈活性:新的主題可以輕鬆集成到現有結構中,而不破壞一致性。
-
效率:客戶端可以訂閱較高層次的廣泛數據概覽或較低層次的非常具體的信息。
上下文相關的命名
使用清晰且有意義的主題名稱,明確傳達上下文和目的。經過深思熟慮、具有上下文意義的命名可以讓用戶更容易理解每個主題的內容和功能,減少潛在的誤解。這增加了易用性並提高了 MQTT 命名空間內的清晰度。
示例:而不是使用 .../data
,可以使用 .../machine1/status
以提供更精確的信息。這可以清楚地表明內容,而無需額外的文檔說明。
集成版本控制
隨着 MQTT 命名空間隨着時間的推移而演變,建議將版本控制集成到 MQTT 主題層次結構中。這使得管理變更更加容易,並確保向後兼容。版本控制允許引入新結構而不影響現有系統。版本控制的集成示例 v1/.../areaID/lineID/cellID
或 mySpec/v1/.../areaID/lineID/cellID
。
其他建議
-
避免將主題名稱弄得過長以提高可讀性。
-
不要使用 MQTT 特定的字符,如 #、+、/ 和 $,因爲這些字符在 MQTT 協議中有特殊功能。主題不應以
/
開頭或結尾,例如/chat
或chat/
。 -
應避免使用空格,因爲它們可能會導致混淆或在某些系統中引起問題。
-
只使用 ASCII 字符,不要使用任何不可打印字符。
-
不要使用
#
訂閱所有主題。 -
使用
_
或-
來連接主題級別內的單詞(或駝峯式寫法)。 -
儘量使用較少的主題層級。
-
儘量在消息數據模式中建模以避免使用通配符主題。
-
當使用通配符時,儘量將更獨特的主題層級移向根部。比如,
device/00000001/command/#
比device/command/00000001/#
更好。
MQTT 主題在 MQTT 客戶端和代理之間建立通信中至關重要。它們可以根據消息內容實現高效的過濾和路由。在 MQTT 基礎系統中確保有效數據交換和處理的關鍵在於正確定義和結構化主題。
MQTT 通配符
MQTT 中,通配符提供了一種強大的機制,可以同時訂閱多個主題。當客戶端訂閱一個主題時,它可以訂閱發佈的消息的確切主題,或者使用通配符來擴展其訂閱範圍。需要注意的是,通配符只能用於訂閱,而不能用於發佈消息。有兩種類型的通配符: single-level
和 multi-level
。
MQTT 通配符 – 單層通配符: +
單級通配符由加號(+)表示,允許替換一個主題級別。通過訂閱包含單級通配符的主題,任何包含通配符位置處任意字符串的主題都將匹配。
例如,訂閱 myhome/groundfloor/+/temperature
可能會產生以下結果:
MQTT 通配符 – 多級:
多級通配符可以覆蓋多個主題級別。它由井號符號 (#) 表示,並且必須作爲主題中的最後一個字符出現,前面跟一個斜槓。
當客戶端訂閱帶有多級通配符的主題時,它會接收到所有以通配符字符前的模式開始的主題的消息,無論主題的長度或深度如何。如果主題僅指定爲 “#”,則客戶端將接收到發送到 MQTT 代理的所有消息。
需要注意的是預期比較大的主題量,訂閱廣泛的主題會導致大量消息被髮送到客戶端,這可能會對系統性能和帶寬使用產生影響。遵循上一節最佳實踐來優化主題訂閱,避免不必要的消息過載。
以 $ 開始的 MQTT 主題
在 MQTT 中,主題命名的靈活性很大,允許您選擇適合您需求的主題名稱。但是,需要注意一個重要的例外情況:以 $ 符號開頭的主題有其特殊用途。這些主題在使用多級通配符 (#) 作爲主題時不會包含在訂閱中。相反,以 $ 開頭的主題是保留給 MQTT 代理的內部統計信息的,提供了對其操作的有價值見解。
以 $ 開頭的主題發佈消息是不允許的,因爲這些主題用於 MQTT 代理向客戶端暴露內部信息和統計信息。雖然目前這些主題沒有官方標準化,但通常會使用前綴 $SYS/ 來表示此類信息,儘管不同實現的代理可能會有所不同。
以下是一些 $SYS 相關的主題說明:
共享訂閱是 MQTT 5.0 的一個特性,是一種在多個訂閱者之間實現負載均衡的訂閱方法。共享訂閱的主題以 $share 開頭。
在以下示意圖中,三個訂閱者使用共享訂閱方法訂閱了同一個主題 $share/g/topic
,其中 topic
是他們實際訂閱的真實主題名稱,而發佈者向 topic
發佈消息,但不向 $share/g/topic
發佈消息。
MQTT 主題常見問題
Q:MQTT 主題的最大層級和長度是多少?
A: MQTT 主題是 UTF-8 編碼的字符串,必須不超過 65535 字節。然而在實踐中,使用更短的主題名稱和更少的層級意味着更少的資源消耗。
儘量不要因爲 “我可以” 就使用更多的主題層級。
例如, my-home/room1/data
比 my/home/room1/data
更好。
Q: 每個主題的數量有限制嗎?
A: 不同的消息服務器對主題的數量有不同的限制。但主題越多,服務器內存的使用量也會越大。鑑於連接到 MQTT 代理的設備數量衆多,我們建議客戶端訂閱不超過十個主題。
Q: 通配符訂閱會降低性能嗎?
A: 當將消息路由到通配符訂閱時,代理可能需要比非通配符主題更多的資源。如果可以避免通配符訂閱,這是一個明智的選擇。
這在很大程度上取決於 MQTT 消息負載中的數據模型。例如,如果發佈者發佈到 device-id/stream1/foo
和 device-id/stream1/bar
,而訂閱者需要訂閱這兩個主題,那麼它可能訂閱 device-id/stream1/#
。更好的替代方案可能是將 foo 和 bar 部分的命名空間推送到負載中,這樣它只發布到一個主題 device-id/stream1
,而訂閱者只需訂閱這個主題即可。
Q: 正常主題和通配符主題的重疊訂閱如何接收消息?
A: 例如,如果一個客戶端同時訂閱了 #
和 test
主題,當發佈到 test
時,它是否會收到兩條重複的消息?這取決於 MQTT 代理的實現。有些會爲每個匹配的訂閱發送消息,因此可能會出現重複。但是,用戶可以利用 MQTT 5.0 訂閱標識符來區分消息來源,並基於標識符在客戶端處理這些重複消息。
Q: 我能否使用共享訂閱和普通訂閱訂閱同一個主題?
A: 但是不推薦這樣做。根據 MQTT 規範,多個訂閱會導致消息重複交付。
參考鏈接:
-
https://randomnerdtutorials.com/what-is-mqtt-and-how-it-works/
-
https://www.emqx.com/en/blog/advanced-features-of-mqtt-topics
-
https://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices/
-
https://i-flow.io/en/ressources/mqtt-topic-namespace-best-practices-step-by-step-guide/
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/uXuWFCV4xPNmt4uohlHphw