我们前面几期重点介绍了MQTT的定义、MQTT发布和订阅架构,以及重要的Message类型详细解说。

我们这期重点介绍MQTT 的灵活性和效率的核心,即两个关键概念:主题Topic和通配符Wildcards。这些功能构成了 MQTT 发布/订阅模型的基础,使得在复杂的物联网生态系统中实现无缝且有针对性的通信成为可能。

MQTT 主题作为消息的地址机制,允许设备和应用程序组织和过滤信息流。它们提供了一种层次结构,可以表示您的物联网系统中的各种方面,从设备位置到传感器类型和数据类别。了解如何有效地设计和利用主题对于创建可扩展且易于管理的物联网解决方案至关重要。
与主题互补的是 MQTT 通配符,这些强大的工具增强了协议的灵活性。通配符允许订阅者同时从多个主题接收消息,简化客户端逻辑并减少网络开销。通过掌握通配符,开发人员可以创建更动态和响应式的物联网应用,能够适应不断变化的数据需求而无需不断重新配置。
接下来我们将深入探讨 MQTT 主题和通配符的复杂性,探索它们的结构、最佳实践和高级功能。

Topic主题指的是一个 UTF-8 字符串,用于过滤连接客户端的消息。主题由一个或多个级别组成,级别之间用正斜杠分隔(主题级别分隔符)。以下是如何为家中办公室的灯创建一个主题的例子:

需要注意的是:主题是区分大小写的,因此这两个主题是不同的:

如果您想通过 MQTT 在家庭办公室中打开一盏灯,可以想象以下场景:


使用Topic最佳的实践指南
以下最佳实践支持创建一个清晰结构化的 MQTT 主题层次结构,这是可扩展的工业统一命名空间(UNS)架构的基础。
1

确保清晰
x/y 和 X/y 被视为两个不同的主题。2

工厂之间的标准化
整个公司的主题结构需要保持一致。这种结构应该适用于所有设施、生产线和机器。同时,可以通过引入专门用于特殊用例的主题来考虑不同组织层级的个别需求,例如 enterprise/site/area/workCell/individual 。
3

粒度 vs. 模块化
在粒度和模块化之间取得良好的平衡至关重要。粒度或模块化的决策应基于您的用例需求。
.../temperature 中的温度值。这使得以有针对性的方式订阅特定事件和数据变得更加容易。
.../sensor 主题中。
4

分层组织
主题结构应反映一个明确定义的层次结构,该层次结构反映了您的工业生态系统中的物理和逻辑结构。主题的树状组织使得可以在较高层次放置更广泛的类别(例如“工厂”或“生产线”),并在其下方放置更具体的主题(例如“订单”或“传感器数据”)。这提供了几个优势:
5

上下文相关的命名
使用清晰且有意义的主题名称,明确传达上下文和目的。经过深思熟虑、具有上下文意义的命名可以让用户更容易理解每个主题的内容和功能,减少潜在的误解。这增加了易用性并提高了 MQTT 命名空间内的清晰度。
示例:而不是使用 .../data ,可以使用 .../machine1/status 以提供更精确的信息。这可以清楚地表明内容,而无需额外的文档说明。
6

集成版本控制
v1/.../areaID/lineID/cellID 或 mySpec/v1/.../areaID/lineID/cellID 。7

其他建议
/ 开头或结尾,例如 /chat 或 chat/ 。
# 订阅所有主题。
_ 或 - 来连接主题级别内的单词(或驼峰式写法)。device/00000001/command/# 比 device/command/00000001/# 更好。MQTT 主题在 MQTT 客户端和代理之间建立通信中至关重要。它们可以根据消息内容实现高效的过滤和路由。在 MQTT 基础系统中确保有效数据交换和处理的关键在于正确定义和结构化主题。

MQTT通配符
MQTT中,通配符提供了一种强大的机制,可以同时订阅多个主题。当客户端订阅一个主题时,它可以订阅发布的消息的确切主题,或者使用通配符来扩展其订阅范围。需要注意的是,通配符只能用于订阅,而不能用于发布消息。有两种类型的通配符: single-level 和 multi-level 。
单级通配符由加号(+)表示,允许替换一个主题级别。通过订阅包含单级通配符的主题,任何包含通配符位置处任意字符串的主题都将匹配。

例如,订阅 myhome/groundfloor/+/temperature 可能会产生以下结果:

MQTT 通配符 – 多级:
多级通配符可以覆盖多个主题级别。它由井号符号 (#) 表示,并且必须作为主题中的最后一个字符出现,前面跟一个斜杠。

当客户端订阅带有多级通配符的主题时,它会接收到所有以通配符字符前的模式开始的主题的消息,无论主题的长度或深度如何。如果主题仅指定为“#”,则客户端将接收到发送到 MQTT 代理的所有消息。

需要注意的是预期比较大的主题量,订阅广泛的主题会导致大量消息被发送到客户端,这可能会对系统性能和带宽使用产生影响。遵循上一节最佳实践来优化主题订阅,避免不必要的消息过载。

以 $ 开始的MQTT主题
在 MQTT 中,主题命名的灵活性很大,允许您选择适合您需求的主题名称。但是,需要注意一个重要的例外情况:以 符号开头的主题有其特殊用途。这些主题在使用多级通配符 (#) 作为主题时不会包含在订阅中。相反,以 开头的主题是保留给 MQTT 代理的内部统计信息的,提供了对其操作的有价值见解。
以 开头的主题发布消息是不允许的,因为这些主题用于 MQTT 代理向客户端暴露内部信息和统计信息。虽然目前这些主题没有官方标准化,但通常会使用前缀 SYS/ 来表示此类信息,尽管不同实现的代理可能会有所不同。
以下是一些$SYS相关的主题说明:

共享订阅是 MQTT 5.0 的一个特性,是一种在多个订阅者之间实现负载均衡的订阅方法。共享订阅的主题以$share 开头。
在以下示意图中,三个订阅者使用共享订阅方法订阅了同一个主题 share/g/topic ,其中 topic 是他们实际订阅的真实主题名称,而发布者向 topic 发布消息,但不向 share/g/topic 发布消息。


MQTT主题常见问题
A: MQTT 主题是 UTF-8 编码的字符串,必须不超过 65535 字节。然而在实践中,使用更短的主题名称和更少的层级意味着更少的资源消耗。
尽量不要因为“我可以”就使用更多的主题层级。
例如, my-home/room1/data 比 my/home/room1/data 更好。
Q:每个主题的数量有限制吗?
A: 不同的消息服务器对主题的数量有不同的限制。但主题越多,服务器内存的使用量也会越大。鉴于连接到 MQTT 代理的设备数量众多,我们建议客户端订阅不超过十个主题。
A: 当将消息路由到通配符订阅时,代理可能需要比非通配符主题更多的资源。如果可以避免通配符订阅,这是一个明智的选择。
这在很大程度上取决于 MQTT 消息负载中的数据模型。例如,如果发布者发布到 device-id/stream1/foo 和 device-id/stream1/bar ,而订阅者需要订阅这两个主题,那么它可能订阅 device-id/stream1/# 。更好的替代方案可能是将 foo 和 bar 部分的命名空间推送到负载中,这样它只发布到一个主题 device-id/stream1 ,而订阅者只需订阅这个主题即可。
A: 例如,如果一个客户端同时订阅了 # 和 test 主题,当发布到 test 时,它是否会收到两条重复的消息?这取决于 MQTT 代理的实现。有些会为每个匹配的订阅发送消息,因此可能会出现重复。但是,用户可以利用 MQTT 5.0 订阅标识符来区分消息来源,并基于标识符在客户端处理这些重复消息。
A: 但是不推荐这样做。根据 MQTT 规范,多个订阅会导致消息重复交付。
参考链接: