前言
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
- 不要忘记可扩展性
主题是一个灵活的概念,不需要预先为其分配空间,但发布者和订阅者双方都应该知晓主题。所以思考如何能在添加新功能时仍可以很好地扩展当前主题就显得尤为重要。例如,当你的智能家居系统需要增加一些新的传感器时,应该可以在不改变主题架构的前提下将其添加进去。