MQTT 主题与通配符(Topics & Wildcards)
MQTT 主题与通配符(Topics & Wildcards)进阶笔记
一、MQTT 主题(Topics)基础
MQTT 的灵活性和高效性核心在于两个关键概念:主题(Topics) 和通配符(Wildcards)。
1.1 什么是 MQTT 主题
MQTT 主题本质上是一个 UTF-8 编码的字符串,是 MQTT 协议进行消息路由的基础。
核心特点:
- 主题类似 URL 路径,使用斜杠
/进行分层,例如:chat/room/1、sensor/10/temperature - 无需提前创建:客户端在订阅或发布时即自动创建主题,开发者无需关心主题的创建,也不需要手动删除主题
- 不同于 Kafka、Pulsar 等消息队列中的主题,MQTT 主题是动态创建的
⚠️ 注意:为了避免歧义且易于理解,通常不建议主题以
/开头或结尾,例如/chat或chat/。
二、MQTT 主题通配符(Wildcards)
通配符主要用于客户端一次订阅多个主题。
⚠️ 重要限制:通配符只能用于订阅,不能用于发布。
2.1 单层通配符(+)
加号 + 用于匹配单个主题层级。
使用规则:
- 必须占据整个层级
- 例如:
+✅ 有效 |sensor/+✅ 有效 |sensor/+/temperature✅ 有效 |sensor+❌ 无效
匹配示例:
订阅主题 sensor/+/temperature 将会收到以下主题的消息:
- ✅
sensor/1/temperature - ✅
sensor/2/temperature - ✅
sensor/n/temperature
但不会匹配以下主题:
- ❌
sensor/temperature(缺少一个层级) - ❌
sensor/bedroom/1/temperature(多出一个层级)
2.2 多层通配符(#)
井号 # 用于匹配主题中任意层级(父级及任意数量的子层级)。
使用规则:
- 必须占据整个层级,且必须是主题的最后一个字符
- 例如:
#✅ 有效(匹配所有主题)|sensor/#✅ 有效 |sensor/bedroom#❌ 无效 |sensor/#/temperature❌ 无效
匹配示例:
订阅主题 sensor/# 将会收到以下主题的消息:
- ✅
sensor - ✅
sensor/temperature - ✅
sensor/1/temperature - ✅
sensor/1/2/3/...(任意深度的子层级)
三、以 $ 开头的特殊主题
3.1 系统主题($SYS/)
以 $SYS/ 开头的主题为系统主题,主要用于获取 MQTT 服务器的运行状态、消息统计、客户端上下线事件等数据。
📌 目前 MQTT 协议暂未明确规定
$SYS/主题标准,但大多数 MQTT 服务器都遵循该标准建议。
EMQX 系统主题示例:
| 主题 | 说明 |
|---|---|
$SYS/brokers |
EMQX 集群节点列表 |
$SYS/brokers/emqx@127.0.0.1/version |
EMQX 版本 |
$SYS/brokers/emqx@127.0.0.1/uptime |
EMQX 运行时间 |
$SYS/brokers/emqx@127.0.0.1/datetime |
EMQX 系统时间 |
$SYS/brokers/emqx@127.0.0.1/sysdescr |
EMQX 系统信息 |
EMQX 还支持客户端上下线事件、收发流量、消息收发、系统监控等丰富的系统主题,用户可通过订阅 $SYS/# 主题获取所有系统主题消息。
📖 详细参考:EMQX 系统主题文档
3.2 共享订阅($share)
共享订阅是 MQTT 5.0 引入的新特性,用于在多个订阅者之间实现订阅的负载均衡。
- MQTT 5.0 规定的共享订阅主题以
$share开头 - 虽然 MQTT 5.0 才正式引入,但 EMQX 从 MQTT 3.1.1 版本开始就支持共享订阅
格式:$share/{群组名}/{真实主题}
例如:$share/g/topic,其中 topic 是真实主题名,$share/g/ 是共享订阅前缀(g 为群组名,可为任意 UTF-8 编码字符串)
📖 对于 MQTT 5.0 以下版本,EMQX 还支持不带群组的共享订阅前缀
$queue。详细参考:EMQX 共享订阅文档
四、不同场景中的主题设计
4.1 智能家居场景
用传感器监测卧室、客厅以及厨房的温度、湿度和空气质量,可以设计以下主题:
myhome/bedroom/temperature
myhome/bedroom/humidity
myhome/bedroom/airquality
myhome/livingroom/temperature
myhome/livingroom/humidity
myhome/livingroom/airquality
myhome/kitchen/temperature
myhome/kitchen/humidity
myhome/kitchen/airquality
订阅策略:
myhome/bedroom/+→ 获取卧室的温度、湿度及空气质量数据myhome/+/temperature→ 获取三个房间的温度数据myhome/#→ 获取所有数据
4.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 |
充电桩发起充电请求前订阅,接收应答 |
4.3 即时消息场景
一对一聊天:
- 主题格式:
chat/user/${user_id}/inbox - 用户上线后订阅该主题,接收好友发送的消息
- 回复时只需将
user_id换为好友的 ID
群聊:
- 主题格式:
chat/group/${group_id}/inbox - 用户加群成功后订阅该主题获取群组消息
- 回复群聊时直接向该主题发布消息
添加好友:
| 主题 | 说明 |
|---|---|
req/user/${user_id}/add |
发布添加好友申请(user_id 为对方 ID) |
req/user/${user_id}/add(订阅) |
用户订阅自己的 ID,接收好友请求 |
resp/user/${user_id}/add |
订阅接收好友请求结果 |
resp/user/${user_id}/add(发布) |
回复好友申请(同意/拒绝) |
用户在线状态:
- 主题格式:
user/${user_id}/state - 用户可以订阅该主题获取好友的在线状态
五、常见问题及解答(FAQ)
Q1:主题的层级及长度有什么限制吗?
MQTT 协议规定主题的长度为两个字节,因此主题最多可包含 65,535 个字符。
💡 建议:主题层级控制在 7 个以内。使用较短的主题名称和较少的主题层级意味着较少的资源消耗。
例如:
my-home/room1/data比my/home/room1/data更好。
Q2:服务器对主题数量有限制吗?
不同消息服务器对最大主题数量的支持各不相同。
- EMQX 默认配置对主题数量没有限制,但主题数量越多将消耗越多的服务器内存
- 建议:一个客户端订阅的主题数量最好控制在 10 个以内
Q3:通配符主题订阅与普通主题订阅性能是否一致?
通配符主题订阅的性能弱于普通主题订阅,且会消耗更多的服务器资源。
💡 用户可根据实际业务情况选择合适的订阅类型。
Q4:重叠订阅了普通主题和通配符主题时如何接收消息?
假如客户端同时订阅了 # 和 test 主题,当向 test 主题发送消息时,是否会收到两条重复消息?
这取决于 MQTT Broker 的实现。例如,EMQX 会为每个匹配的订阅发送消息。
💡 用户可以使用 MQTT 5.0 中的订阅标识符来区分消息来源,然后在客户端中根据订阅标识符来处理这类重复的消息。
Q5:同一个主题能被共享订阅与普通订阅同时使用吗?
可以,但不建议同时使用。
六、主题设计最佳实践
| 序号 | 建议 |
|---|---|
| 1 | ❌ 不建议使用 # 订阅所有主题 |
| 2 | ❌ 不建议主题以 / 开头或结尾,例如 /chat 或 chat/ |
| 3 | ❌ 不建议在主题里添加空格及非 ASCII 特殊字符 |
| 4 | ✅ 同一主题层级内建议使用下划线 _ 或横杆 - 连接单词(或使用驼峰命名) |
| 5 | ✅ 尽量使用较少的主题层级 |
| 6 | ✅ 当使用通配符时,将唯一值的主题层(例如设备号)越靠近第一层越好。例如,device/00000001/command/# 比 device/command/00000001/# 更好 |
七、总结
| 概念 | 核心要点 |
|---|---|
| 主题 | UTF-8 字符串,/ 分层,无需预创建 |
单层通配符 + |
匹配单个层级,只能用于订阅 |
多层通配符 # |
匹配任意层级,必须放在最后,只能用于订阅 |
$SYS/ |
系统主题,获取服务器状态信息 |
$share |
共享订阅(MQTT 5.0),实现负载均衡 |
| 主题设计 | 层级 ≤ 7,订阅数 ≤ 10,命名规范,避免 # 全量订阅 |
📖 延伸阅读:MQTT 入门与进阶系列文章

浙公网安备 33010602011771号