前言
topic 的數量隨着業務的增長逐漸增多,如何正確的設計 topic 成了當務之急。在這篇文章中,將重點討論MQTT 主題和最佳實踐。
Topics
- 分隔符"/"
topic是UTF-8字符串,broker用於過濾客戶端的消息,一個topic由一個或多個主題層組成,每個主題級別用/分割。
home/floor/room/sensor
通配符
- 單級通配符:"+"
單一級別的通配符可以代替一個主題級別,如果包含任意字符串而不是通配符,則任何主題都與包含單級通配符的主題相匹配:
home/floor/+/temp //此主題訂閱與以下主題匹配或不匹配,√:匹配 ×:不匹配
home/floor/kitchen/temp √
home/floor/room/temp √
home/floor/kitchen/brightness ×
home/firstfloor/kitchen/temp ×
home/floor/kitchen/fridge/temp ×
- 多級通配符:"#"
多級通配符覆蓋任意數量的主題級別,必須是主題中的最後一個字符,並且前面有/,例如:
home/floor/# //此主題訂閱與以下主題匹配或不匹配,√:匹配 ×:不匹配
home/floor/kitchen/temp √
home/floor/livingroom/brightness √
home/firstfloor/kitchen/temp ×
Topic,payload設計方案
topic和payload設計方案一般有如下兩種,當然還有其它更多的組合
//1.topic攜帶儘可能多的信息 payload
plant1/machineA/sensorX/temp/value 20
plant1/machineA/sensorX/temp/unit ℃
plant1/machineA/sensorX/temp/date 2020-04-11 12:12:12
//2.topic payload攜帶儘可能多的信息
plant1/machineA/
{
["sensorX": {
"value": 20,
"unit": "C",
"timestamp": "2018-08-01T12:00:30.123Z"
}
]
}
儘管可以按照自己的喜好設計topic,應當注意的是,不同的設計會帶來不同的影響,除了影響語義的清晰性,也可能影響系統性能。
例如屋子裏有10個傳感器,
在風格house/sensor01…house/sensor1中,house/sensor01 消息只發給sensor01(只有一個訂閱者)
在風格house中,10個傳感器都訂閱它,payload爲{“sensor01”:“on”}的消息將發送給10個傳感器,每個傳感器都需要檢查消息以查看他是否適合自己。
因此有如下建議:
-
爲單個設備或一小組設備使用相同的topic
-
爲data和commands使用單獨的topic
-
消息payload中的數據應該是特定設備的
-
消息payload中與設備的多個屬性相關的數據是json編碼的
topic命名注意:
-
每個主題必須至少有一個有效的字符,可以包含空格,區分大小寫。
-
不要在最前面加/,例如:
/home/floor/house
等於在最前面有一個空字符串層級,完全沒有必要,且增加了broker的處理,
home/floor/house
纔是合理的。
-
使用英文+數字字符,不要使用空格、特殊字符,會增加處理的複雜性,以及帶來可能的兼容性問題
-
將設備id或者識別碼包含在topic中,便於訂閱特定設備、後續過濾、權限控制
-
命名簡單明確,太長了看太累,看不懂會困惑,容易出錯,topic應該儘可能詳細,能定位到不同的設備和消息
如果你有三個傳感器在臥室中,你應該這樣命名主題:
myhome/livingroom/temperature,
myhome/livingroom/brightness,
myhome/livingroom/humidity,
而不是通過myhome/livingroom發送所有的值。這樣也便於你使用其他的 MQTT 功能,
- 命令字保持一致,放在最後,例如:
home/bedroom/bedlight/rgb/set
- 不要忘記可擴展性
主題是一個靈活的概念,不需要預先爲其分配空間,但發佈者和訂閱者雙方都應該知曉主題。所以思考如何能在添加新功能時仍可以很好地擴展當前主題就顯得尤爲重要。例如,當你的智能家居系統需要增加一些新的傳感器時,應該可以在不改變主題架構的前提下將其添加進去。