0%

MQTT主题实战技巧-通配符的正确打开方式

引言

随着物联网(IoT)设备的广泛部署,MQTT(Message Queuing Telemetry Transport)作为一种轻量级的消息协议,因其高效、低带宽占用和易于实现等优点,成为了IoT设备间通信的首选。在MQTT中,主题(Topic)是消息传递的关键概念之一,它定义了消息发布者与订阅者之间的通道。今天我们就来深入探讨一下MQTT中的主题以及如何利用通配符来优化消息过滤。

一、什么是 MQTT 主题

  • 在MQTT中,主题是一种层次结构的字符串,用于确定消息的路由路径。每个主题由一个或多个用斜杠(/)分隔的主题级别组成,例如home/livingroom/temperature。发布者将消息发送到特定主题,而订阅者则可以订阅感兴趣的主题以接收消息。主题是区分大小写的,并且不包含空格或其他特殊字符。

主题设计的最佳实践

  • 简洁明了:尽量保持主题简洁,避免过长。
  • 逻辑清晰:使用有逻辑意义的主题层级帮助识别信息类型或来源。
  • 灵活可扩展:考虑未来可能的扩展性,设计足够通用的主题结构。

通配符介绍

为了提高消息订阅的灵活性,MQTT提供了两种类型的通配符:单层通配符(+)和多层通配符(#).

  • 单层通配符(+): 可以用来替换主题中的某一级别。例如,订阅home/+/temperature将会匹配home/livingroom/temperaturehome/kitchen/temperature,但不会匹配home/livingroom/kitchen/temperature

  • 多层通配符(#): 位于主题过滤器的末尾,可以匹配剩余的所有层级。比如,订阅home/#将会匹配home/livingroom/temperaturehome/kitchen/temperature甚至home/livingroom/kitchen/temperature

  • 以 $ 开头的主题: 有些MQTT Broker的系统主题就是以$SYS/开头的

  • 注意:通配符只能用于订阅,不能用于发布消息的主题。

使用通配符的实际应用案例

1、智能家居
  • 假设我们正在构建一个智能家居系统,其中需要监控不同房间的温度、湿度等环境数据。通过合理使用通配符,我们可以轻松地设置一些通用的订阅规则:

    • 订阅home/+/temperature来获取家中所有房间的温度信息。
    • 或者使用home/livingroom/#来收集客厅内所有类型的数据。
  • 这种方式不仅简化了代码,还提高了系统的灵活性和可维护性。

2、充电桩

充电桩的上行主题格式为 ocpp/cp/${cid}/notify/${action},下行主题格式为 ocpp/cp/${cid}/reply/${action}

  • ocpp/cp/cp001/notify/bootNotification
    充电桩上线时向该主题发布上线请求。
  • ocpp/cp/cp001/notify/startTransaction
    向该主题发布充电请求。
  • ocpp/cp/cp001/reply/bootNotification
    充电桩上线前需订阅该主题接收上线应答。
  • ocpp/cp/cp001/reply/startTransaction
    充电桩发起充电请求前需订阅该主题接收充电请求应答。
3、即时消息
  • chat/user/${user_id}/inbox

    一对一聊天:用户上线后订阅该收件箱主题 ,将能接收到好友发送给自己的消息。给好友回复消息时,只需要将该主题的 user_id 换为好友的的 id 即可。

  • chat/group/${group_id}/inbox

    群聊:用户加群成功后,可订阅该主题获取对应群组的消息,回复群聊时直接给该主题发布消息即可。

  • req/user/${user_id}/add

    添加好友:可向该主题发布添加好友的申请(user_id 为对方的 id)。
    接收好友请求:用户可订阅该主题(user_id 为自己的 id)接收其他用户发起的好友请求。

  • resp/user/${user_id}/add

    接收好友请求的回复:用户添加好友前,需订阅该主题接收请求结果(user_id 为自己的 id)。
    回复好友申请:用户向该主题发送消息表明是否同意好友申请(user_id 为对方的 id)。

  • user/${user_id}/state
    用户在线状态:用户可以订阅该主题获取好友的在线状态。

二、MQTT 主题常见问题及解答

1、主题的层级及长度有什么限制吗?
  • 答:对于主题的总长度(包括所有层级和斜杠),不同的MQTT代理可能有不同的限制。一些常见的MQTT代理如Mosquitto默认允许的最大主题长度为65535字节。因此,在使用时最好查阅所使用的MQTT代理的相关文档以了解其具体限制。
2、MQTT主题是否区分大小写?
  • 答:是的,MQTT主题是区分大小写的。例如,Home/Light和home/light被视为两个不同的主题。
3、MQTT主题的最大长度是多少?
  • 答:对于主题的总长度(包括所有层级和斜杠),不同的MQTT代理可能有不同的限制。一些常见的MQTT代理如Mosquitto默认允许的最大主题长度为65535字节。因此,在使用时最好查阅所使用的MQTT代理的相关文档以了解其具体限制
4、通配符可以在发布消息时使用吗?
  • 答:不可以,通配符只能用于订阅消息,不能用于发布消息的主题。这意味着你不能向一个包含通配符的主题发布消息。
5、通配符订阅会不会影响性能?
  • 答: 使用通配符订阅确实会增加代理的匹配复杂度,尤其是在大规模连接或高频率消息发布的环境中。虽然现代MQTT Broker优化较好,但在性能敏感场景下仍需谨慎使用。

  • 实际应用案例: 某智慧城市项目中,10万个路灯节点上报状态至各自独立主题如 city/street/light/00001/status。如果监控中心使用通配符订阅 city/street/light/# 来获取所有灯的状态,可能会造成较大的资源消耗。

  • 解决方案:

    • 对于高频采集的数据,建议使用特定主题分组聚合;
    • 或使用边缘计算节点先做本地汇总,再统一上传;
    • 对于低频或非关键数据,才考虑通配符订阅。
6、重叠订阅了普通主题和通配符主题时如何接收消息?
  • 答:假如客户端同时订阅了 # 和 test 主题,当向 test 主题发送消息时,是否会收到两条重复消息?这取决于 MQTT broker 的实现,例如 EMQX 会为每个匹配的订阅发送消息。但是用户可以使用 MQTT 5.0 中的订阅标识符来区分消息来源,然后在客户端中根据订阅标识符来处理这类重复的消息。
7、常见的 MQTT 主题使用建议有哪些?
  • 不建议使用 # 订阅所有主题;
  • 不建议主题以 / 开头或结尾,例如 /chatchat/
  • 不建议在主题里添加空格及非 ASCII 特殊字符;
  • 同一主题层级内建议使用下划线 _ 或横杆 - 连接单词(或者使用驼峰命名);
  • 尽量使用较少的主题层级;
  • 当使用通配符时,将唯一值的主题层(例如设备号)越靠近第一层越好。例如,device/00000001/command/#device/command/00000001/# 更好。
8、如何有效地使用单层(+)和多层(#)通配符?
  • 答:单层通配符(+)用来匹配单一层级的主题,而多层通配符(#)则必须位于主题过滤器的末尾,用来匹配多个层级的主题。合理使用这些通配符可以帮助更灵活地订阅感兴趣的消息,比如home/+/temperature会匹配任何房间的温度信息,而home/#则会匹配家中的所有信息。
9、如果订阅了一个不存在的主题会发生什么?
  • 答:如果你订阅了一个当前没有任何发布者发送消息的主题,那么你将不会收到任何消息,直到有消息被发布到该主题。MQTT代理不会因为你订阅了未使用的主题而返回错误或警告。
10、能否通过主题实现远程控制设备?
  • 答: 当然可以。MQTT支持双向通信,可以通过为主题设计控制指令通道来实现远程控制。

  • 实际应用案例: 智能家居中,灯光控制器订阅如下主题:

1
home/light/livingroom/control

用户通过APP向该主题发送控制指令(如开/关、亮度调整等),设备接收到消息后执行对应操作。
示例消息内容:

1
2
3
4
{
"command": "on",
"brightness": 75
}

类似地,还可以为风扇、窗帘、空调等设备设计类似的控制主题结构。

11. 如何防止主题被误用或滥用?
  • 答: 可以通过权限管理(ACL)和命名规范来限制谁可以发布或订阅哪些主题。
  • 实际应用案例: 在工业物联网平台中,每个工厂车间有各自的命名空间,如:
1
2
factory/plantA/line1/data
factory/plantB/line2/data

系统通过MQTT Broker配置访问控制列表(ACL),确保Plant A的操作人员只能访问plantA相关主题,避免越权访问。

同时,对命令类主题(如 /control)设置更高权限,防止未经授权的设备发起控制操作。

12、如何用主题实现设备状态反馈?
  • 答: 可以为每台设备定义一个“状态”主题,用于反馈其运行状态或错误信息。
  • 实际应用案例: 在物流车队管理系统中,每辆车都有一个状态主题,例如:
1
2
vehicle/bus001/status
vehicle/truck002/status

车载终端定时发布位置、速度、油量、故障码等信息,监控中心订阅这些主题以实时掌握车辆状况。
如果某辆车出现故障,可通过专用主题如:

1
vehicle/bus001/alert

发送警报通知,以便快速响应。

三、结语

  • 理解和正确使用MQTT的主题与通配符对于开发高效的物联网应用至关重要。它们使得我们可以更智能地管理和筛选来自大量设备的信息流,从而为用户提供更加个性化的服务体验。希望本文能帮助你更好地掌握这些概念,并在实际项目中加以运用。
您的打赏,是我创作的动力!不给钱?那我只能靠想象力充饥了。