在 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:“把这条消息送到 room1 的 temperature 地址去。”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。 |
共享订阅
共享订阅 Topic Filter 以如下方式配置:
$share/{ShareName}/{TopicFilter}参数 | 说明 |
$share | 字面常量,固定字符串。 |
{ShareName} | 是共享订阅组名称,不能包含“ / ”,“ + ” , “ # ”。 |
{TopicFilter} | 与 MQTT TopicFilter 要求和语义相同。 |
MQTT Topic 使用建议
1. 区分大小写:
myhome/temp 和 MyHome/Temp 是完全不同的两个主题。2. 层级与字符限制:
层级深度:建议控制在 7 层以内。层级越深,Broker 匹配资源的消耗越大。
字符类型:每个主题必须包含至少一个字符;避免空格和非 ASCII 特殊字符。
命名规范:同一主题层级内建议使用下划线“_” 或横杆“-” 连接单词(或者使用驼峰命名)
3. 唯一标识前置:当使用通配符时,将唯一值的主题层(例如设备号)越靠近第一层越好。如:
device/{deviceID}/status 优于 device/status/{deviceID}。4. 文档化:维护全面的文档,详细说明您的 MQTT 主题结构,包括其用途、预期的消息负载等完整的约定或指南。
常见问题
主题的层级及长度有什么限制吗?
MQTT 协议规定主题的长度为两个字节,因此主题最多可包含 65,535 个字符。
建议主题层级为 7 个以内。使用较短的主题名称和较少的主题层级意味着较少的资源消耗,例如
my-home/room1/data 比 my/home/room1/data 更好。服务器对主题数量有限制吗?
不同消息服务器对最大主题数量的支持各不一致,目前默认对主题数量没有限制,但是主题数量越多将会消耗越多的服务器内存以及路由查找的开销。考虑到连接到 MQTT Broker 的设备数量一般较多,我们建议一个客户端订阅的主题数量最好控制在 10 个以内。
通配符主题订阅与普通主题订阅性能是否一致?
通配符主题订阅的性能弱于普通主题订阅,且会消耗更多的服务器资源,用户可根据实际业务情况选择订阅类型。
系统主题如何使用?