【译文】MQTT 主题&通配符&最佳实践 – MQTT 基础: 第五部分

459 阅读10分钟

原文:www.hivemq.com/blog/mqtt-e…

本篇文章在翻译过程中,对相关内容进行了一些删减,比如文字超链接

作者: HiveMQ Team
发表于: August 20, 2019
更新: 2023年6月20日

MQTT主题在MQTT生态系统中至关重要,因为代理服务器依赖它们来确定哪些客户端接收特定的消息。下面是MQTT基本知识的第五部分,我们将重点介绍MQTT主题、MQTT通配符,并详细探讨使用它们的最佳实践。在本文中,我们还将研究SYS主题,这些主题提供了对代理服务器本身的深入了解。

如果您想了解MQTT中的发布、订阅和取消订阅,请参阅本系列的第四部分。我们开始学习吧。

什么是MQTT 主题,它在MQTT消息过滤机制的角色是什么?

在MQTT协议中,Topic 指的一个UTF-8编码过的字符串,这个字符串可以用来过滤已经连接上代理服务器的客户端。 主题的结构是由中间用斜杠(主题层级分隔符)分隔成一个或多个层级组成的。

topic_basics.png

MQTT 层级结构

与消息队列相比,MQTT主题非常轻量级。客户端在发布或订阅所需的主题之前不需要创建该主题。代理服务器接受每个有效的主题,也不需要事先进行任何初始化。

MQTT 主题样例

列举一些MQTT主题的例子:

  1. myhome/groundfloor/livingroom/temperature: 这个主题表达的意思是:位于一楼卧室的温度
  2. USA/California/San Francisco/Silicon Valley: 这个主题表达的意思是: 追踪或交换与美国加利福尼亚州旧金山硅谷地区相关的事件或数据的信息
  3. 5ff4a2ce-e485-40f4-826c-b1a5d81be9b6/status: 这个主题可以用于监测唯一标识的设备的状态或是系统状态
  4. Germany/Bavaria/car/2382340923453/latitude: 这个主题可用来共享德国巴伐利亚地区特定汽车的纬度坐标

MQTT主题的最佳实践

列举一些MQTT最佳实践的主题:

  • 每个主题必须包含至少一个字符
  • 主题字符串可以包含一些空格,以便于阅读或者描述主题
  • 主题会区分大小写的,如"myhome/temperature" 和 "MyHome/Temperature" 会被认为是两个完全不同的主题
  • 单独的正斜杠就是一个有效的主题,可以用来表示一个广泛的主题,也可以用作同时订阅多个主题的通配符

MQTT主题在MQTT客户端和代理服务器之间建立通信是非常重要的。它们能够根据消息的内容进行有效的过滤和路由。正确定义和结构化主题对于确保基于MQTT系统内的有效数据交换和处理至关重要。

MQTT通配符是什么,如何用它订阅主题?

在MQTT协议中,通配符提供了一个强大的机制,可同时订阅多个主题。当客户端订阅一个主题时,既可以订阅已发布过消息的准确主题,也可以使用通配符扩大订阅范围。注意的是,通配符仅仅用于订阅消息,不能用于发布消息。通配符有两种类型: 单级(single-level) 和多级 (multi-level).

MQTT 通配符 – 单级(Single Level): +

单级通配符是通过符号"+"来表示的,它允许替代主题中的一个层级。通过单层级通配符订阅主题,将匹配通配符所在位置的任意字符串主题。

topic_wildcard_plus.png

例如, 订阅这个主题 myhome/groundfloor/+/temperature,会产生如下订阅结果:

topic_wildcard_plus_example.png

MQTT 通配符 – 多级(Multi Level):

多层级通配符可覆盖主题中的多个层级,多层级通配符使用“#”号表示,必须做为主题最后一个字符串,且前边紧挨着一个正斜杠。

topic_wildcard_hash.png

当客户端订阅了一个带通配符的主题,它将接收以通配符以外字符串开始的主题。如果以“#”号单独订阅主题,客户端会接收MQTT服务器所有的消息。

topic_wildcard_hash_example.png

但是,如果需要高吞吐量,那么单独使用多层级通配符订阅可能是一种反模式,这一点很重要。订阅宽泛的主题可能会导致向客户端发送大量消息,可能会影响系统性能和带宽使用。遵循最佳实践来优化主题订阅并避免不必要的消息过载。

何时用$开始的MQTT主题,使用$符号的原因是什么

在MQTT中,主题命名的灵活性非常大,允许您选择适合您需要的名称。但是,有一个重要的例外需要注意: 以$符号开头的主题是另有用途的。当使用多级通配符(#)作为主题时,订阅中不包括这些主题。相反,以 $开头的主题是预留给MQTT代理服务器内部统计信息用的,从而为其操作提供有价值的见解。

禁止发布以$开头的主题,因为这些主题是用作MQTT代理服务器对客户端呈现内部信息和数据统计。虽然目前还没有针对这些主题的正式标准化,但是通常使用前缀$SYS/来表示这些信息,尽管代理服务器的具体实现可能有所不同。

推荐一个理解$SYS主题的文章MQTT GitHub wiki.

下面是一些$SYS主题的示例以及它们可以提供的信息:

  1. $SYS/broker/clients/connected: 表示当前已连接代理服务器客户端的数量
  2. $SYS/broker/clients/disconnected: 表示已从和代理服务服务器断开的客户端数量
  3. $SYS/broker/clients/total: 表示与MQTT代理服务器已连接和已断开的客户端的数量
  4. $SYS/broker/messages/sent: 表示通过MQTT代理服务器已发送消息的数量
  5. $SYS/broker/uptime: 表示MQTT代理服务器连续运行的时间

这些$SYS主题为了解MQTT代理服务器的内部工作和性能提供了有价值的见解,使管理员和开发人员能够监视和分析关键的统计数据。

通过理解以$开头的主题的目的和重要性,您可以有效地利用这个约定来更深入地了解MQTT基础结构的行为和性能。

探究MQTT主题的动态属性

这些都是MQTT消息主题的基础。正如你看到的,MQTT主题是动态的,具有较大的灵活性。当你在真实应用中使用通配符时,会面临一些挑战。我们已经搜集到一些最佳实践,这些都是我们在不同项目用总结出来的宝贵经验,我们也欢迎大家对这些实践发出讨论和给出建议。使用评论开始一次对话,让我们知道你的最佳实践或者你对我们最佳实践异议是什么

MQTT 最佳实践

避免使用正斜杠开始主题

虽然MQTT允许在主题(如‘/myhome/ground/living’)中使用前导斜杠,但它引入了一个不必要的主题级别,前面的字符为零。这可能会导致混淆(前面的字符为零) ,而不会带来任何好处。因此,建议删除前面的正斜杠

永远不要在MQTT主题中使用空格

空格是每个程序员的天敌。主题中的空格可能会妨碍可读性和调试工作,特别是在故障排除期间。此外,UTF-8有许多不同的空格类型。我们建议不要在MQTT主题中完全使用空格和不常用字符。

保持MQTT主题简洁明了

请记住,每条消息中都会包含一个主题。为了优化网络流量和节省宝贵的资源,努力使您的主题简洁明了。这在处理资源受限的设备(每个字节都很重要)时尤其关键。

只使用ASCII字符,避免使用不可打印的字符

为了确保主题表示的一致性和准确性,最好坚持使用ASCII字符。非ASCII UTF-8字符可能显示不正确,识别错误或字符集相关的问题会引入挑战性。除非必要,否则不要在MQTT主题中使用非ASCII字符。

主题中嵌入唯一标识符或客户端ID

为了增强消息识别和强制授权,可以考虑在主题中嵌入发布客户端的唯一标识符或客户端ID,这能让你识别消息发送者身份和控制发布权限。例如,具有client1 ID的客户端可以发布到“client1/status”,但不能发布到“client2/status”。

避免订阅通配符(#)

有时,需要订阅通过代理服务器传输的所有消息。例如,将所有消息保存到数据库中。不要通过使用MQTT 客户端和多层级通配符来订阅代理服务器上的所有消息。通常,客户端无法消费由此方法产生的消息(特别是在吞吐量很大的情况下)。我们的建议是在MQTT代理服务器中实现一个扩展。例如,使用 HiveMQ 扩展 ,您可以连接到 HiveMQ 的行为,并添加一个异步例程来处理每个传入消息并将其持久化到数据库。

拥有可扩展性

MQTT中的主题提供了固有的灵活性,允许将来的扩展和新特性。考虑好你的主题结构如何能够适应未来或新增传感器及功能的添加。设计主题以促进可扩展性,而不必整个的更改主题层级结构。例如,如果您的智能家居解决方案添加了新的传感器,那么应该可以在不改变整个主题层次结构的情况下将这些传感器添加到主题层级结构中。

使用特定的主题,而不是一般的主题

区分主题以反映特定的数据流或实体。避免对多种类型的消息使用单个主题。例如,如果你的客厅里有三个传感器,那就创建一些主题,比如myhome/livingroom/temperaturemyhome/livingroom/brightnessmyhome/livingroom/humidity而不是使用myhome/livingroom这样的通用主题。此实践提高了识别度,并支持使用高级 MQTT 特性,例如保留消息。要了解更多信息,请阅读我们关于MQTT retained messages的文章。

文档

维护详细的MQTT主题文档,包括它们的用途、预期的消息有效负载以及任何相关的约定或指导。这有助于加入新的团队成员,并促进更好的协作。

持续改进

基于不断变化的需求和反馈,时常回顾和优化你的主题结构。拥抱持续改进的心态,以确保高效和可扩展的 MQTT通信。

安全考虑:

确保您的主题结构和命名约定不会无意中暴露敏感信息。通过适当的访问控制和身份验证机制,以保护 MQTT通信。

总结

MQTT基础课程系列的第五部分结束了。总之,在MQTT中,主题可以灵活而高效做为消息主干。通过理解复杂性和应用最佳实践,可以优化MQTT实现,以获得最佳性能和可伸缩性。

在本文中,我们探讨了MQTT主题的动态特性,深入研究了通配符的使用、技术注意事项和推荐的策略。我们讨论了避免在主题中使用正斜杠开头和空格、保持主题简洁、利用ASCII字符和嵌入唯一标识符或客户端 ID 的重要性。我们还强调了不使用通配符订阅所有消息的重要性以及主题设计中可扩展性的价值。

通过遵循这些最佳实践,您可以增强MQTT基础设施的可读性、可维护性和安全性。我们希望本文提供了有价值的见解和可操作的信息,以提升您的MQTT项目。感谢您参与我们关于复杂的MQTT主题之旅。我们希望你发现这篇文章有价值和信息。