边缘 AI MQTT 加固 + 离线缓冲可执行手册
调研日期:约 2026-10-25(Asia/Shanghai)
定位:站内自托管 Broker 选型、鉴权/ACL、Topic/QoS、断线有界缓冲、断 MQTT 不堵推理硬门禁;与 IEC 60870-5-104 只读边界对齐。
上游衔接:edge-ai-event-schema-acceptance.md(Schema/Topic)、edge-ai-model-signstore-mender-cookbook.md(OTA 轨)、edge-ai-substation-gateway-bom.md(AI VLAN)、edge-ai-scada-104-pointlist-template.md(104 点表)、edge-ai-license-ledger-template.md(许可台账)。
许可声明:下文 SPDX/许可以官网与 GitHub LICENSE 核验为准;嵌入产品/集群等场景须法务复核。不确定处标 unknown。
1. 目标与硬红线
| # | 红线 | 说明 |
|---|---|---|
| R1 | 禁止匿名 | Broker 生产配置 allow_anonymous false(或等价);测试口也不得对站外开放 |
| R2 | 断 MQTT 不堵推理 | 发布路径必须异步 + 有界队列;满则按策略丢弃,不得阻塞解码/NPU |
| R3 | MQTT ≠ 遥控总线 | 下行 cmd 仅限阈值/启停路/抓拍/重载模型等运维动作;禁止经 MQTT 下发跳闸、软压板、GOOSE、保护定值 |
| R4 | 与保护网隔离 | Broker 只落 AI VLAN / 管理信息大区;104/61850 由协议网关 只读镜像,默认 severity=suspect |
| R5 | 站内自托管优先 | 公有云 MQTT SaaS 默认不进站端主路径;4G/5G 仅白名单备路 |
验收否决项(对齐 Schema 手册):人为断开 Broker ≥5 分钟,解码与推理 FPS 相对断线前跌落 ≤5%;恢复后不得 OOM。
2. Broker 短名单(站内自托管)
| Broker | 典型部署 | SPDX / 许可要点(核验约 2026-10) | MQTT | TLS / 鉴权 | 站端建议 |
|---|---|---|---|---|---|
| Eclipse Mosquitto | 单站 / 边端轻量 | EPL-2.0 OR BSD-3-Clause(双许可) | 3.1 / 3.1.1 / 5.0 | 用户口令、证书、ACL 文件、动态安全插件 | 默认首选(单站盒旁或站控小机) |
| NanoMQ | 网关同机 / 极轻量边 | MIT | 3.1.1 / 5.0 | TLS、口令;可选 SQLite 持久化发行版 | 同盒旁路或资源紧时 |
| EMQX | 地市汇聚 / 多站 | ≤5.8:Apache-2.0;≥5.9:BSL 1.1(单节点生产有 Additional Use Grant;集群/嵌入商用产品常需商业许可) | 3.1–5.0 | 丰富鉴权/ACL、桥接 | 汇聚层;版本钉死并台账;嵌入网关产品须法务 |
| VerneMQ | 可选集群 | 源码 Apache-2.0;官方二进制/Docker 另有 EULA(商用生产常需订阅) | 3.1–5.0 | TLS、插件鉴权、离线队列 | 自编译可规避包 EULA;预编译走法务 |
选型口诀
- 单站试点 / A–B 档网关旁:Mosquitto(稳、文档熟、许可清晰)。
- 算力盒内存紧、要同机旁路:NanoMQ(MIT,边向)。
- 多站汇聚、规则引擎:评估 EMQX 钉版本(≤5.8 Apache 轨,或 5.9+ 单节点 BSL 条款);禁止未审就把 EMQX 嵌进对外销售的网关镜像。
- 全部进许可台账:组件名、版本、SPDX、是否嵌入分发、法务结论。
3. Topic / QoS / ACL(对齐既有 Schema)
3.1 Topic 树(与 Schema 手册一致)
edgeai/{org}/{site}/{device_id}/events/{task} # 告警/检出,QoS1
edgeai/{org}/{site}/{device_id}/frames/{cam} # 可选帧摘要,QoS0,强节流
edgeai/{org}/{site}/{device_id}/telemetry # 功耗/温度/FPS/mqtt_q,QoS0(或1)
edgeai/{org}/{site}/{device_id}/status # retained online/offline,QoS1
edgeai/{org}/{site}/{device_id}/cmd/# # 下行运维,QoS1;ACL 严控
edgeai/{org}/{site}/{device_id}/ota/ack # 可选:模型/Artifact 校验结果上报
另:MODEL_VERIFY_FAIL 等运维事件走 events/ops 或 telemetry 扩展字段,勿塞保护通道。
3.2 QoS 与 Retain
| 通道 | QoS | Retain | 备注 |
|---|---|---|---|
| events | 1 | 否 | 要送达语义;客户端本地仍须有界缓冲 |
| frames | 0 | 否 | 可丢;断线优先丢 |
| telemetry | 0(默认) | 否 | 水位紧张时最先丢 |
| status | 1 | 是 | LWT 配 offline;上线发 online |
| cmd | 1 | 否 | 仅运维账号可发 |
禁止对高频 events/frames 开 Retain(Broker 磁盘与陈旧告警风险)。
3.3 ACL 最小权限(示意)
设备证书/device_id 绑定用户名,例如 dev-box-rk3588-07:
| 主体 | 允许 publish | 允许 subscribe |
|---|---|---|
| 边缘盒 | edgeai/{org}/{site}/{device_id}/events/#、.../frames/#、.../telemetry、.../status、.../ota/ack |
edgeai/{org}/{site}/{device_id}/cmd/# |
| 站内告警订阅者 | — | edgeai/{org}/{site}/+/events/#、.../status |
| 运维看板 | — | .../telemetry、.../status |
| 运维下发账号 | .../cmd/#(按站) |
可选 .../status |
| 协议网关(MQTT→104) | — | .../events/#、.../status(只订不发) |
跨站通配 # 禁止给设备账号。cmd 禁止设备互发。
4. 鉴权:口令 vs mTLS
4.1 推荐分层
| 环境 | 传输 | 客户端认证 | 说明 |
|---|---|---|---|
| 实验室单机 | TLS 可选 | 强口令 + ACL | 仍关匿名 |
| 站内生产(默认) | TLS 1.2+ | 设备证书(mTLS) 或「口令+按设备独立账号」 | 证书 CN/SAN = device_id |
| 地市跳板 | TLS | 运维账号 + IP 白名单 | 与设备账号分离 |
| 4G 备路 | TLS | 同生产;域名白名单 | 禁止裸 1883 出站 |
口令轨:mosquitto_passwd(或等价)每设备独立哈希;禁止共享 admin/admin。
mTLS 轨:站内 CA 签设备证;吊销用 CRL/短有效期轮换(对齐签名仓密钥轮换节奏)。
匿名:生产与联调对外口一律关闭。
4.2 Mosquitto 配置骨架(可复制)
# /etc/mosquitto/conf.d/edgeai.conf — 示例,按站改路径
listener 8883
protocol mqtt
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/broker.crt
keyfile /etc/mosquitto/certs/broker.key
require_certificate true # mTLS;若仅口令则 false + password_file
use_identity_as_username true # CN 作 username,便于 ACL
allow_anonymous false
# password_file /etc/mosquitto/passwd # 口令轨启用
acl_file /etc/mosquitto/acl
persistence true
persistence_location /var/lib/mosquitto/
max_queued_messages 1000 # Broker 侧上限;边缘侧仍要有本地有界队列
ACL 片段:
user dev-box-rk3588-07
topic write edgeai/grid-east/SS-220-01/box-rk3588-07/events/#
topic write edgeai/grid-east/SS-220-01/box-rk3588-07/frames/#
topic write edgeai/grid-east/SS-220-01/box-rk3588-07/telemetry
topic write edgeai/grid-east/SS-220-01/box-rk3588-07/status
topic read edgeai/grid-east/SS-220-01/box-rk3588-07/cmd/#
user gw-104-readonly
topic read edgeai/grid-east/SS-220-01/+/events/#
topic read edgeai/grid-east/SS-220-01/+/status
NanoMQ / EMQX:等价关闭匿名、TLS 监听、按 clientid/device_id ACL;具体键名以所选版本文档为准(EMQX 5.9+ 许可见上表)。
5. 离线缓冲:本地队列 + 水位 + 补传
5.1 架构硬门禁
[解码] → [NPU 推理] → [Schema 适配] → [有界 Publish Queue] ──async──► MQTT Client
│ │
│ 永不 join/阻塞 ├─ 在线:直发
▼ └─ 离线/背压:落盘缓冲
继续下一帧
规则:
- 推理线程 只
try_enqueue;队列满 → 按丢弃策略,0 阻塞。 - MQTT 客户端独占 IO 线程/协程;
PUBLISH/reconnect超时不得回调进推理线程。 - 本地缓冲与 Broker
max_queued_messages解耦:边缘必须自有持久层。
5.2 存储选型
| 方案 | 适用 | 要点 |
|---|---|---|
| SQLite(推荐默认) | 工业 SSD/eMMC | 表:id, pri, topic, qos, payload, ts_utc, msg_id;WAL;单文件易备份 |
| 环形文件 | 极简/只追加 | 定长槽位或长度前缀;满则覆盖最旧 低优先级 |
| 纯内存 ring | 仅 POC | 掉电丢;生产须落盘 |
5.3 优先级与丢弃(水位)
定义优先级(高→低):
- P0
status/ LWT 相关、MODEL_VERIFY_FAIL、关键events(severity≥high或点表已映射的event.code) - P1 普通
events - P2
telemetry - P3
frames
水位示例(可按盘容量改):
| 水位 | 条件(示例) | 动作 |
|---|---|---|
| 绿 | 占用 < 60% 或 < 5k 条 | 正常入队 |
| 黄 | 60–85% | 停收 P3 frames;telemetry 降采样(如 30s→120s) |
| 红 | > 85% 或字节上限 | 丢 P2 telemetry 与 P3;P1 可按「同 code 合并/只留最新」;尽量保 P0 |
| 危 | 即将写满 | 只保 P0;记 mqtt_drop_* 计数进后续 telemetry |
原则:优先丢 telemetry(与 frames),保事件。
5.4 恢复后补传顺序
- 先发 status=online(retained)。
- 按
ts_utc升序、同刻按 优先级高先 补传;使用原msg_id便于云端幂等。 - 限速(如 50–200 msg/s)避免打爆 Broker/4G;补传期间推理仍只走
try_enqueue。 - 成功收到 PUBACK(QoS1)或本地确认策略后删行;失败退避重试,禁止忙等。
- 断源过久:协议网关侧 104 点品质置「源不确定」(见点表模板),不得把最后一条告警当「已确认真实」无限保持。
5.5 缓冲伪代码骨架
# 示意:推理回调中禁止 network I/O
PRI = {"status": 0, "events": 1, "telemetry": 2, "frames": 3}
def on_infer_result(msg: dict, channel: str):
item = pack(msg, channel) # topic/qos/payload/msg_id/ts
if not pub_q.try_enqueue(item, pri=PRI[channel]):
metrics.inc(f"mqtt_drop_{channel}")
# 不抛、不等、不重试阻塞
return
# 立刻返回,继续下一帧
# 独立线程
def mqtt_worker():
while True:
if client.connected:
drain_online(pub_q, client) # 先内存再 SQLite
else:
spill_to_sqlite(pub_q) # 达黄/红水位执行丢弃策略
client.reconnect_backoff()
6. 「断 MQTT 不堵推理」验收测法
| 步骤 | 操作 | 通过标准 |
|---|---|---|
| 1 | 稳态跑 N 路约定负荷 ≥10 min,记录 fps_in/fps_infer、队列深度 |
基线曲线存档 |
| 2 | iptables/ip link 或停 Broker,断开 ≥5 min(合同可写 30 min 加严) |
fps_infer 跌落 ≤5% |
| 3 | 观察 RSS/FD/线程;SQLite 体积 | 无 OOM;无推理线程卡在 mqtt_publish |
| 4 | 恢复链路,观察补传 | 有界限速;P0/P1 优先;telemetry 可丢 |
| 5 | 抽查 Schema | health.mqtt_q、mqtt_drop_* 有值;msg_id 可幂等 |
否决:推理线程 join 网络调用、无界 std::queue、断线后 FPS 腰斩、恢复后内存涨死。
7. 与保护网 / 104 只读边界
摄像机/传感 ──► AI 边缘网关 ──AI VLAN──► MQTT Broker
│ │
│ ├─► 告警平台 / 对象存储
│ └─► 协议网关(只订 events/status)
│ │
│ ▼
│ IEC 60870-5-104 只读上送
│ (YX/YC 镜像,品质可标 suspect)
x 禁止:MQTT cmd → 跳闸/软压板/GOOSE/定值
落地条款:
- Broker、模型仓、推理盒与 保护装置不同二层域;交换机 ACL 默认 deny。
- MQTT
cmd白名单:set_threshold/start_cam/stop_cam/reload_model/snap_now等;无trip/breaker/interlock类 action。 - 104 点表主键 = MQTT
event.code;网关 只订不发。 - 4G 备路仅解析 MQTT/OTA 域名;不承载保护业务。
8. 两周落地清单
| 日 | 动作 | 产出 |
|---|---|---|
| D1 | 选定 Broker(默 Mosquitto)+ 版本钉死;写入许可台账 | 台账行 + SPDX |
| D2 | 站内 CA 或口令方案;关匿名;TLS 监听 8883 | 证书/口令文件 |
| D3 | 落地 ACL(按 device_id);划 AI VLAN |
acl 文件 + 交换机 ACL |
| D4 | 边缘客户端:异步有界队列 + SQLite 缓冲骨架 | 代码合入 |
| D5 | 对接统一 Schema Topic;status LWT | 样例报文 |
| D6 | 丢弃策略水位可配;metrics:mqtt_q/mqtt_drop_* |
配置项 |
| D7 | 与 104 网关联调:只订 events;点表 3~5 个 code | 升沿/品质 |
| D8 | 断 MQTT ≥5 min 验收;录 FPS | 实验记录 |
| D9 | 恢复补传限速 + 幂等抽查;红水位演练 | 报告附表 |
| D10 | cmd 白名单评审;确认无遥控语义 | 纪要 |
| D11 | 4G 备路白名单(若有);备份 Broker 配置 | 运维手册半页 |
| D12–14 | 压力:多路满载 + 反复断线;修队列泄漏;归档配置进签名仓旁「运维包」 | 签字验收 |
9. 许可台账预填(须法务复核)
| 组件 | 建议钉版本策略 | SPDX/许可 | 嵌入网关分发 | 备注 |
|---|---|---|---|---|
| Eclipse Mosquitto | 跟发行版 LTS | EPL-2.0 OR BSD-3-Clause | 通常可 | 双许可选一遵循 |
| NanoMQ | 跟 GitHub release | MIT | 通常可 | 注意可选依赖(JWT/QUIC 等)许可 |
| EMQX | 慎升 5.9+ | ≤5.8 Apache-2.0;≥5.9 BSL-1.1 | 集群/嵌入商用常受限 | 单节点 Additional Use Grant ≠ 可任意嵌入销售 |
| VerneMQ | 源码自建 vs 官方包 | 源码 Apache-2.0;官方包 EULA | 官方包商用看订阅 | 预编译勿想当然 |
10. 与系列文档交叉引用
| 主题 | 文件 |
|---|---|
| Topic / JSON / 断线验收条款 | edge-ai-event-schema-acceptance.md |
| 模型 OTA 与错签事件 | edge-ai-model-signstore-mender-cookbook.md |
| AI VLAN / 三档 BOM | edge-ai-substation-gateway-bom.md |
| MQTT→104 点表 | edge-ai-scada-104-pointlist-template.md |
| SPDX 红线 | edge-ai-license-ledger-template.md |
11. 小结
站端 MQTT 以 Mosquitto/NanoMQ 自托管 为主,EMQX/VerneMQ 按汇聚与许可审慎选用;Topic 严格对齐 Schema;TLS + 禁匿名 + 按设备 ACL;本地 SQLite/环形缓冲 且 优先丢 telemetry 保事件;推理路径 异步有界、断线 FPS 跌落 ≤5% 为否决项;MQTT 绝不充当遥控/保护总线,104 仅只读镜像。按两周清单可完成从 Broker 加固到断线验收的最小闭环。