Topic 与通配符订阅

最近更新时间:2025-11-27 16:21:22

我的收藏
在 MQTT 构建的物联网世界中,发布-订阅(Publish/Subscribe)模式实现了设备与应用之间的完全解耦,而支撑这一机制运转的核心,正是主题(Topic)
与通配符(Wildcard)。
作为一个基于 UTF-8 编码的字符串,Topic 类似于 URL 路径,采用分层结构(如 sensor/room1/temperature),它不仅是消息传递的寻址通道,更是业务逻辑在通信层面的映射。在消息流转过程中,发布者向特定 Topic 发送数据,代理服务器(Broker)则依据订阅者的需求进行精准路由。
为了应对海量设备的复杂通信需求,MQTT 引入了通配符订阅机制。这把“精准匹配”扩展为“模式匹配”,允许客户端通过一次订阅捕获多条相关数据流,极大地降低了网络负载与客户端逻辑的复杂度。因此,深入理解 Topic 的分层逻辑并掌握通配符的用法,是构建可扩展、易维护且高性能物联网系统的第一步。

Topic Name、Topic Filter 与 Topic

在 MQTT 协议通信机制中有三个角色: 消息发布者(publisher)、代理服务器(broker)和消息订阅者(subscriber)。消息从发布者发送到代理服务器,然后被订阅者接收,而主题就是发布者与订阅者之间约定的消息通道。为了实现精准的消息路由,我们需要明确三个角色的定义:

Topic Name(主题名)

定义:发布消息时使用的字符串。
用途:标识特定消息的唯一通道。
规则严禁包含通配符。它必须是一个确定的、具体的路径。
示例sensor/room1/temperature。发布者告诉 Broker:“把这条消息送到 room1temperature 地址去。”

Topic Filter(主题过滤器)

定义:订阅消息时使用的字符串。
用途:告诉 Broker 您希望接收哪些消息。
规则可以使用通配符,也可以不使用(即精确匹配)。它本质上是一个“匹配模板”。
示例
sensor/+/temperature:订阅者告诉 Broker:“我要所有房间的温度数据。”
sensor/room1/temperature:订阅者告诉 Broker:“我只要 room1 的温度数据。”

Topic(主题)

定义:它是 Topic Name 和 Topic Filter 在 Broker 内部匹配后形成的逻辑通道。
关系:Broker 负责将 Topic Name(消息来源)与 Topic Filter(订阅需求)进行匹配。如果匹配成功,消息就会被投递。
说明:
消息队列 MQTT 版中,Topic无需预先创建。客户端在订阅或发布消息时会自动创建主题,并且无需删除主题。
为了更好地理解上述区别,我们来看一个典型的MQTT发布和订阅流程示意图:APP 1 订阅了sensor/+/temperature这个主题,将接收到 Sensor 1和 Sensor 2发布的消息;APP 2订阅了sensor/2/temperature主题后,将能接收到 Sensor 2 发布到该主题的消息。


MQTT 通配符

MQTT 通配符是一种特殊的主题类型,只能用于订阅(仅用于 Topic Filter 中),不能用于发布。客户端可以订阅含有通配符的主题来接收来自多个匹配主题的消息,从而灵活地订阅多个 Topic,降低了开销。MQTT 支持两种类型的通配符:+单层通配符和#多层通配符。

单层通配符

单层通配符用加号+表示,允许用于匹配单个层级主题。该通配符必须占据一个完整的层级,不能只是层级的一部分(如 room+ 是非法的)。通过订阅带有单层通配符的主题,可以匹配到所有在通配符位置上是任意字符串的主题。例如:
订阅 sensor/+/temperature
匹配 sensor/bedroom/temperature
匹配 sensor/living_room/temperature
不匹配 sensor/bedroom/upstairs/temperature (因为+只能匹配一层)
不匹配 sensor/temperature (因为 sensor 和 temperature 之间缺少一层)

多层通配符

多层通配符用井号#表示,代表匹配零个或多个任意主题层级。必须是主题过滤器的最后一个字符,前面加上一个斜杠。例如:
订阅 sensor/bedroom/#
匹配 sensor/bedroom/temperature
匹配 sensor/bedroom/humidity
匹配 sensor/bedroom/light/intensity
匹配 sensor/bedroom (# 可以匹配零层)
不匹配 sensor/living_room/temperature (因为 bedroom 是固定的)
注意:如果业务预期吞吐量较高,仅使用多层通配符进行订阅可能是一种“坏”模式。订阅范围过广的主题会导致大量消息发送到客户端,从而可能影响系统性能和带宽使用。请遵循最佳实践来优化Topic Filter的设计,避免不必要的消息过载。

$ 开头的 MQTT Topic

事件主题 $events

MQTT 系统将触发的事件以 QoS=0 消息发布到以下系统主题,业务系统可根据业务需要订阅。
主题名称
备注
$events/client_connected
客户端已连接。
$events/client_disconnected
客户端已断开连接。
$events/session_subscribed
客户端会话新增了订阅。
$events/session_unsubscribed
客户端会话取消了订阅。
$events/certificate_registered
客户端注册了设备证书。
$events/certificate_rejected
客户端设备证书被拒绝, 证书状态为非激活状态,例如 PENDING_ACTIVATION。

共享订阅

共享订阅是 MQTT 5.0 引入的新特性,用于在多个订阅者之间实现订阅的负载均衡,MQTT 5.0 规定的共享订阅主题以 $share 开头。
共享订阅 Topic Filter 以如下方式配置:$share/{ShareName}/{TopicFilter}
参数
说明
$share
字面常量,固定字符串。
{ShareName}
是共享订阅组名称,不能包含“ / ”,“ + ” , “ # ”。
{TopicFilter}
与 MQTT TopicFilter 要求和语义相同。

MQTT Topic 使用建议

1. 区分大小写myhome/tempMyHome/Temp 是完全不同的两个主题。
2. 层级与字符限制
层级深度:建议控制在 7 层以内。层级越深,Broker 匹配资源的消耗越大。
字符类型:每个主题必须包含至少一个字符;避免空格和非 ASCII 特殊字符。
命名规范:同一主题层级内建议使用下划线“_” 或横杆“-” 连接单词(或者使用驼峰命名)
3. 唯一标识前置:当使用通配符时,将唯一值的主题层(例如设备号)越靠近第一层越好。如:device/{deviceID}/status 优于 device/status/{deviceID}
4. 文档化:维护全面的文档,详细说明您的 MQTT 主题结构,包括其用途、预期的消息负载等完整的约定或指南。

常见问题

主题的层级及长度有什么限制吗?

MQTT 协议规定主题的长度为两个字节,因此主题最多可包含 65,535 个字符。
建议主题层级为 7 个以内。使用较短的主题名称和较少的主题层级意味着较少的资源消耗,例如 my-home/room1/datamy/home/room1/data 更好。

服务器对主题数量有限制吗?

不同消息服务器对最大主题数量的支持各不一致,目前默认对主题数量没有限制,但是主题数量越多将会消耗越多的服务器内存以及路由查找的开销。考虑到连接到 MQTT Broker 的设备数量一般较多,我们建议一个客户端订阅的主题数量最好控制在 10 个以内。

通配符主题订阅与普通主题订阅性能是否一致?

通配符主题订阅的性能弱于普通主题订阅,且会消耗更多的服务器资源,用户可根据实际业务情况选择订阅类型。

系统主题如何使用?

根据业务需要订阅具体某类事件对应的topic,详见事件主题$events。订阅$events/#将收到所有客户端事件的消息。