内容:
1.MQTT主题和最佳实践
正文
主题(Topic)
- 在 MQTT 中,主题一词是指代理用于为每个连接的客户端过滤消息的 UTF-8 字符串。主题由一个或多个主题级别组成。每个主题级别由正斜杠(主题级别分隔符)分隔。
- 与消息队列相比,MQTT 主题非常轻量级。客户端在发布或订阅它之前不需要创建所需的主题。代理接受每个有效主题而无需任何事先初始化。
以下是一些主题示例:
我的家/一楼/客厅/温度
美国/加利福尼亚/旧金山/硅谷
5ff4a2ce-e485-40f4-826c-b1a5d81be9b6/status
Germany/Bavaria/car/2382340923453/latitude
请注意,每个主题必须至少包含1 个字符,并且主题字符串允许有空格。主题区分大小写。例如,myhome/temperature和MyHome/ Temperature是两个不同的主题。此外,单独的正斜杠是一个有效的主题。
通配符
当客户端订阅主题时,它可以订阅已发布消息的确切主题,也可以使用通配符同时订阅多个主题。通配符只能用于订阅主题,不能用于发布消息。有两种不同类型的通配符:单级和多级。
-
单级:+
顾名思义,单级通配符替换一个主题级别。加号代表主题中的单级通配符。
如果主题包含任意字符串而不是通配符,则任何主题都与具有单级通配符的主题匹配。例如,订阅myhome/groundfloor/+/temperature可以产生以下结果:
-
多级:#
多级通配符涵盖多个主题级别。哈希符号代表主题中的多级通配符。为了让代理确定哪些主题匹配,多级通配符必须作为主题中的最后一个字符放置,并以正斜杠开头。
当客户端订阅带有多级通配符的主题时,无论主题多长或多深,它都会收到以通配符之前的模式开头的主题的所有消息。如果你仅将多级通配符指定为主题 ( # ),你将收到发送到 MQTT 代理的所有消息。如果你期望高吞吐量,单独使用多级通配符订阅是一种反模式(请参阅下面的最佳实践)。
以 "$" 开头的主题 (格式问题 该符号在下面用“d”代替)
- 通常,你可以根据需要命名 MQTT 主题。但是,有一个例外:以 d 符号开头的主题具有不同的目的。当你将多级通配符作为主题 (#) 订阅时,这些主题不是订阅的一部分。d-symbol 主题保留用于 MQTT 代理的内部统计信息。客户端无法向这些主题发布消息。目前,此类主题尚无官方标准化。通常,dSYS/用于所有以下信息,但代理实现各不相同。MQTT GitHub wiki中提供了对 $SYS-topics 的一项建议 。这里有些例子:
$SYS/broker/clients/connected
$SYS/broker/clients/disconnected
$SYS/broker/clients/total
$SYS/broker/messages/sent
$SYS/broker/uptime
最后
- 如你所见,MQTT 主题是动态的并提供了极大的灵活性。在实际应用程序中使用通配符时,应该注意一些挑战。下面是收集了在各种项目中学到的最佳实践:
最佳实践
切勿使用前导正斜杠
MQTT 中允许使用前导正斜杠。例如, /myhome/groundfloor/livingroom。但是,前导正斜杠引入了一个不必要的主题级别,前面有一个空字符。空字符不提供任何好处,并且经常导致混淆。永远不要在主题中使用空格
空格是每个程序员的天敌。当事情没有按照应有的方式进行时,空格会使阅读和调试主题变得更加困难。与前导斜杠一样,仅仅因为允许某些东西,并不意味着应该使用它。UTF-8有许多不同的空白类型,应避免使用此类不常见字符。保持主题简短
每个主题都包含在使用它的每条消息中。使您的主题尽可能简短。对于小型设备,每个字节都很重要,主题长度会产生很大影响。仅使用 ASCII 字符,避免不可打印的字符
由于非 ASCII UTF-8 字符经常显示不正确,因此很难找到与字符集相关的拼写错误或问题。除非绝对必要,否则建议避免在主题中使用非 ASCII 字符。将唯一标识符或客户端 ID 嵌入到主题中
在主题中包含发布客户端的唯一标识符会非常有帮助。主题中的唯一标识符可帮助您识别消息的发送者。嵌入的 ID 可用于强制执行授权。只有与主题中的 ID 具有相同客户端 ID 的客户端才被允许发布到该主题。例如,允许具有client1 ID的客户端发布到client1/status,但不允许发布到client2/status。不要订阅#
有时,需要订阅通过代理传输的所有消息。例如,将所有消息持久化到数据库中。不要通过使用 MQTT 客户端和订阅多级通配符来订阅代理上的所有消息。通常,订阅客户端无法处理由此方法产生的消息负载(尤其是当您有大量吞吐量时)。不要忘记可扩展性
主题是一个灵活的概念,无需以任何方式预先分配它们。但是,发布者和订阅者都需要了解主题。重要的是要考虑如何扩展主题以允许新功能或产品。例如,如果您的智能家居解决方案添加了新传感器,则应该可以将它们添加到您的主题树中,而无需更改整个主题层次结构。使用特定主题,而不是一般主题
命名主题时,不要像在队列中那样使用它们。尽可能区分你的主题。例如,如果您的客厅有三个传感器,请为myhome/livingroom/temperature、myhome/livingroom/brightness和myhome/livingroom/humidness创建主题 。不要通过myhome/livingroom*发送所有值。对所有消息使用单个主题是一种反模式。特定命名还使您可以使用其他 MQTT 功能,例如保留消息。