| 名称 | mqtt-topic-design |
| 描述 | 当需要为物联网设备设计或评审 MQTT 主题层级、QoS 等级、保留消息、遗嘱消息与会话策略时使用。该技能先盘点设备与消息流,再产出可落地的主题命名规范、投递语义决策表和迁移方案,并用脚本校验主题合法性。适用于智能家居、工业物联网、车联网、共享设备等多设备接入场景。关键词:MQTT、主题设计、Topic、QoS、保留消息、遗嘱消息、Last Will、会话保持、Clean Session、共享订阅、通配符、设备影子、物联网通信、消息协议、EMQX、Mosquitto。 |
MQTT 主题与投递语义设计评审
为一组设备与业务消息设计一套“十年不用改”的 MQTT 主题体系,并为每条消息流确定 QoS、保留消息(Retain)、遗嘱消息(Last Will)与会话策略。
何时使用
- 新项目要定义 MQTT 主题规范,但团队各写各的。
- 已有主题混乱:大小写混用、层级过深、把设备 ID 写进业务字段、通配符滥用。
- 设备频繁掉线,需要判断是否该用保留消息、遗嘱消息或持久会话。
- 从单租户升级到多租户,需要做主题迁移而不中断存量设备。
不适用:纯 HTTP/WebSocket 消息总线;MQTT 5 属性级调优(可作为第二阶段单独处理)。
输入
收集以下信息,缺失项按“待确认”记录,不要臆造:
- 设备类型、数量级、固件是否可以升级。
- 消息方向:设备上报、平台下发、设备间。
- 每条消息的业务语义:遥测、事件、命令、配置、状态、固件分片。
- 网络条件:是否蜂窝、是否长离线、是否按流量计费。
- 现有主题样例(有则优先兼容)。
工作流
第 1 步:消息清单
先把消息按六类归档,再谈命名:
| 类别 | 方向 | 典型语义 | 是否允许丢失 |
|---|---|---|---|
| telemetry(遥测) | 上行 | 周期采集值 | 允许丢旧值 |
| event(事件) | 上行 | 告警、故障、按键 | 不允许丢 |
| command(命令) | 下行 | 控制指令 | 不允许丢,不允许重复执行 |
| config(配置) | 双向 | 参数下发与确认 | 不允许丢 |
| state(状态) | 上行 | 在线状态、设备影子 | 只关心最新 |
| ota(固件升级) | 双向 | 固件分片与进度 | 分片可重传 |
第 2 步:主题层级
统一使用 7 层以内的固定骨架,从左到右由稳定到易变:
{namespace}/{tenant}/{deviceType}/{deviceId}/{channel}/{aspect}
namespace:产品线或协议版本,如v1、iot。tenant:多租户隔离键;单租户可省略整层,不要用空字符串占位。deviceType:设备品类,小写短横线连接,如smart-plug。deviceId:设备唯一标识,只允许[a-z0-9_-]。channel:telemetry/event/cmd/cfg/state/ota。aspect:具体指标或动作,如temperature、reboot。
约束:
- 全部小写;不使用空格、中文、
#、+、$、前导/、结尾/。 - 发布主题禁止包含通配符,通配符只出现在订阅端。
- 不要把时间戳、随机数、序列号放进主题层级;它们是载荷字段。
- 业务参数(房间号、产线号)放载荷,不放主题,避免主题基数爆炸。
第 3 步:投递语义
对每条消息流按 references/qos-matrix.md 的决策表确认 QoS、retain、会话:
- 命令必须 QoS 1,并携带幂等键;QoS 2 仅在计费或不可重复扣减场景使用。
- 在线状态用 retain + 遗嘱消息,让新订阅者立即拿到最后状态。
- 遥测默认 QoS 0;采样频率高于 1 Hz 时考虑批量聚合后发送。
- 持久会话只给命令与配置类客户端,避免离线消息堆积拖垮 broker。
第 4 步:多租户与通配符
- 订阅端使用
{namespace}/{tenant}/+/+/telemetry/#,禁止#置顶订阅全库。 - 若 broker 支持,按租户做 ACL:
allow readwrite {namespace}/{tenant}/#。 - 共享订阅使用
$share/{group}/{topic},消费组按服务名命名。
第 5 步:校验与迁移
- 运行
scripts/validate_topics.py topics.txt,修复全部错误项。 - 对存量设备给出双写期方案:新主题与旧主题并行,保留消息做状态镜像,按固件版本灰度下线旧主题。
- 输出迁移表:旧主题 → 新主题 → 生效版本 → 回滚方式。
检查清单
- [ ] 每条消息都能归入六类之一,无“其他”。
- [ ] 主题深度 ≤ 7,全小写,无非法字符。
- [ ] 发布主题无通配符,订阅主题未使用顶层
#。 - [ ] 设备 ID 与租户隔离有 ACL 兜底。
- [ ] 命令具备幂等键与去重窗口。
- [ ] 遗嘱消息与保留消息的清理策略已定义(设备注销、租户删除)。
- [ ] 主题基数估算已给出,未出现按用户/时间分片的高基数层级。
输出模板
## 消息清单
| 消息 | 类别 | 方向 | 主题 | QoS | Retain | 会话 | 幂等键 |
| --- | --- | --- | --- | --- | --- | --- | --- |
## 主题规范
骨架:...
命名规则:...
禁止项:...
## ACL 建议
...
## 迁移方案
| 旧主题 | 新主题 | 生效版本 | 回滚方式 |
| --- | --- | --- | --- |
## 风险
- ...
反模式
- 用
device/{id}/data一把梭,所有消息挤在同一主题靠载荷字段区分。 - 用 QoS 2 解决“命令重复执行”,真正的解法是幂等键。
- 给高频遥测开 retain,broker 每秒都在重写保留消息。
- 用持久会话承接海量遥测离线消息,内存被离线队列吃满。
- 主题里放时间戳,导致每台设备每天产生上千个主题。
参考文件
references/topic-patterns.md:常见行业主题骨架与字段约定。references/qos-matrix.md:QoS / retain / 会话决策表与故障对照。scripts/validate_topics.py:主题规范静态校验脚本。