MQTT集群
上万台吊挂控制板时,不能按“1 台 MQTT 服务器 + 1 个业务程序”来做。应采用:
控制板直连 MQTT Broker 集群;显示面板只走服务器业务层;服务器是唯一的业务控制中心;工厂现场具备断网可恢复与局部自治能力。
MQTT Broker 集群前应部署四层负载均衡,Broker 采用多节点集群,后端业务服务采用无状态多实例部署。EMQX 等 MQTT 平台支持集群、负载均衡及共享订阅,适合将大量控制板连接和服务端消息消费横向扩展。(EMQX 文档)

一、推荐总体架构
┌──────────────────────────────┐
│ 中央平台 / 管理端 │
│ Web后台、报表、配置、审计、BI │
└──────────────┬───────────────┘
│
┌─────────────▼─────────────┐
│ 业务服务集群 │
│ │
│ ① MQTT消息接入服务 │
│ ② 吊挂命令服务 │
│ ③ 工位/衣架业务服务 │
│ ④ 设备在线状态服务 │
│ ⑤ 面板消息推送服务 │
└───────┬───────────┬────────┘
│ │
┌───────────▼───┐ ┌──▼──────────────┐
│ Redis 集群 │ │ PostgreSQL/MySQL │
│ 在线状态、锁、 │ │ 设备、工单、参数、│
│ 指令关联、缓存 │ │ 执行记录、审计 │
└───────────────┘ └─────────────────┘
│
┌───────────▼────────────────────┐
│ MQTT Broker 集群 │
│ Broker-1 / Broker-2 / Broker-3 │
│ Active-Active 多节点运行 │
└───────────┬────────────────────┘
│
┌───────────▼───────────┐
│ 双机负载均衡 / VIP │
│ HAProxy / F5 / Nginx L4 │
└───────┬─────────┬──────┘
│ │
┌──────────────▼─┐ ┌──▼─────────────────┐
│ 吊挂控制板群 │ │ 显示面板/终端机群 │
│ 1万台、5万台… │ │ Terminal │
│ Hanger │ │ 只能通过服务器控制 │
└────────────────┘ └────────────────────┘
对于单一大型工厂,建议先按“3 台 Broker + 2 台负载均衡 + 3 个以上业务服务实例”作为高可用起点。实际节点数量不能只按“1 万台设备”确定,还要按峰值消息量、心跳周期、断线重连风暴、衣架过站频率和命令并发量压测后确定。
二、控制板、服务器、面板的正确关系
1. 吊挂控制板直接连接 Broker
每台控制板作为 MQTT Client,直接连接负载均衡 VIP,而不是连接显示面板,也不要让显示面板转发控制板消息。
吊挂控制板 → MQTT Broker 集群 → 业务服务器
控制板负责:
-
上报上线、心跳、衣架进站、加工点信息、报警、数据采集;
-
接收服务器指令;
-
返回执行结果;
-
可向指定显示面板发布提示信息。
2. 显示面板不能直接控制吊挂控制板
面板发起的操作必须经过服务器校验。
显示面板
↓ Terminal/ToServer
业务服务器
↓ 权限、工单、站位、状态校验
Hanger/线号/站位号
↓
吊挂控制板
这样可以避免终端机被误操作、被替换或被攻击后,直接启动电机、恢复出厂或修改关键参数。
3. 吊挂控制板可直接通知面板
你现在定义的模式可以保留:
吊挂控制板 → Terminal/终端机号 → 显示面板
适用于:
-
当前站位衣架到达;
-
进站失败;
-
缺少衣架;
-
设备报警;
-
员工号、工单号、款号显示;
-
需要显示的提示文字。
但是控制板只能向面板“推送显示消息”,面板不能直接向 Hanger/线号/站位号 发布控制命令。
三、MQTT Broker 层如何部署
1. 不能使用单台 MQTT 服务器
单机即使当前能承受 1 万台连接,也存在明显风险:
-
单机宕机,全厂吊挂通信中断;
-
系统升级、维护会影响所有控制板;
-
网络连接、CPU、内存、文件句柄都集中在一台机器;
-
大批控制板同时重连时容易形成连接风暴。
建议使用 Broker 集群,前面配置 VIP 或四层负载均衡。EMQX 官方文档明确支持集群节点、负载均衡、健康检查及节点重平衡。(EMQX 文档)
2. 推荐部署方式
VIP:mqtt.company.local:8883
│
┌────────────────┴────────────────┐
│ │
LB-01 主用 LB-02 备用
│ │
┌──────┴───────┬────────────┬────────────┘
│ │ │
Broker-01 Broker-02 Broker-03
建议:
-
MQTT 通信端口使用
8883,启用 TLS; -
控制板使用唯一
ClientId; -
每台控制板使用独立账号或独立证书;
-
Broker、数据库、业务服务不要部署在同一台服务器;
-
Broker 节点至少跨 3 台物理机或虚拟机;
-
负载均衡至少双机部署;
-
工厂网络与办公网络隔离,控制板处于工业 VLAN 内。
四、现有 Topic 在大规模系统中的处理方式
你现有协议可以继续使用:
| 用途 | Topic |
|---|---|
| 控制板上报服务器 | Hanger/ToServer |
| 服务器回应控制板上报 | Hanger/ToServer/Answer |
| 服务器下发控制板 | Hanger/线号/站位号 |
| 控制板回应服务器命令 | Hanger/线号/站位号/answer |
| 控制板通知面板 | Terminal/终端机号 |
| 面板上报服务器 | Terminal/ToServer |
但是在上万台控制板规模下,建议后续增加版本化 Topic。
Hanger/V2/工厂号/车间号/线号/站位号/Up
Hanger/V2/工厂号/车间号/线号/站位号/Down
Hanger/V2/工厂号/车间号/线号/站位号/Answer
Terminal/V2/工厂号/终端机号/Notify
例如:
Hanger/V2/F01/W01/L001/S025/Up
Hanger/V2/F01/W01/L001/S025/Down
Hanger/V2/F01/W01/L001/S025/Answer
Terminal/V2/F01/T10025/Notify
这样做的好处是:
-
Broker 可以按工厂、车间、线体、站位做权限控制;
-
可按线体拆分服务器消费能力;
-
查询某个站位的问题更方便;
-
后期多工厂部署时不会混乱;
-
便于灰度升级新旧控制板协议。
MQTT Topic 支持层级结构和通配符订阅,因此这类分层 Topic 更适合设备分组、授权和运维。(EMQX 文档)
五、Hanger/ToServer 如何避免成为瓶颈
不能让多个业务服务都各自订阅:
Hanger/ToServer
否则一条控制板消息可能被多个服务重复处理。
应该使用共享订阅,让多个“控制板接入服务”共同消费消息:
$share/hanger-ingress/Hanger/ToServer
例如部署 6 个吊挂接入服务实例:
吊挂控制板 → Hanger/ToServer
↓
$share/hanger-ingress/Hanger/ToServer
↓
接入服务01 ~ 接入服务06
同一条上报消息只会由共享订阅组中的一个服务实例处理;服务实例增加后,处理能力可横向扩展。共享订阅的机制就是同一订阅组内只由一个消费者接收消息,而不同订阅组仍可各自收到完整消息流。(EMQX 文档)
建议划分为:
$share/hanger-ingress/Hanger/ToServer
用于实时业务处理。
$share/hanger-store/Hanger/ToServer
用于数据入库。
$share/hanger-alarm/Hanger/ToServer
用于报警识别和设备监控。
六、QoS 与“业务应答”必须分开理解
这是吊挂控制最容易出问题的地方。
MQTT QoS 只能表示消息传输层的可靠程度,不代表吊挂控制板已经真正执行成功。
| 类型 | 建议 QoS | 是否还要业务应答 |
|---|---|---|
| 心跳 | QoS 0 或 QoS 1 | 建议不逐条业务应答 |
| 设备上线 | QoS 1 | 要 |
| 衣架进站、加工信息 | QoS 1 | 要 |
| 报警上报 | QoS 1 | 要 |
| 参数读取、参数设置 | QoS 1 | 要 |
| 启动电机、停止电机 | QoS 1 | 必须要 |
| 恢复出厂设置 | QoS 1 | 必须要 |
| 高频采样数据 | QoS 0 或 QoS 1 | 按业务决定 |
QoS 1 是“至少一次”传输,可能产生重复消息;QoS 2 开销更大。即使使用 QoS 1,也仍然必须保留你定义的:
Hanger/ToServer/Answer
Hanger/线号/站位号/answer
因为 MQTT 的 PUBACK 只能说明 Broker 接收了消息,不能说明“服务器已经处理完成”或“控制板电机已经真正执行成功”。MQTT 标准也明确说明 QoS 1 可能重复、QoS 2 传输成本更高。(OASIS)
七、协议建议补充 MessageId 与 RequestId
你当前 JSON 中只有:
{
"LineNo": "L001",
"StationNo": "S025",
"Time": "2026-06-23 10:30:00",
"Command": 105,
"Data": {
"Run": true
}
}
大规模系统中建议补充两个字段:
{
"MessageId": "8a1dc04d-0c76-4e83-84fa-100001",
"RequestId": "CMD-20260623-00000001",
"LineNo": "L001",
"StationNo": "S025",
"Time": "2026-06-23 10:30:00",
"Command": 105,
"Data": {
"Run": true
}
}
控制板应答:
{
"RequestId": "CMD-20260623-00000001",
"Time": "2026-06-23 10:30:01",
"Command": 105,
"ResultCode": 0,
"Message": "电机已启动",
"Data": {
"Run": true
}
}
建议统一规定:
| 字段 | 用途 |
|---|---|
MessageId |
当前消息唯一编号,用于上报去重 |
RequestId |
服务器命令编号,用于命令与应答关联 |
ResultCode |
0 成功;非 0 为失败代码 |
Message |
失败或执行结果说明 |
ExpireAt |
指令有效截止时间 |
Seq |
控制板递增流水号 |
BootId |
控制板本次上电编号 |
特别是“启动电机、恢复出厂、参数设置”这类命令,控制板必须按 RequestId 去重。服务器重发同一个命令时,控制板只能返回上次执行结果,不能重复启动电机或重复恢复出厂。
八、指令状态机必须在服务器保存
服务器不能“发布完 MQTT 命令就认为成功”,应保存完整状态:
创建命令
↓
待发送
↓
已发布 Broker
↓
控制板已接收
↓
执行成功 / 执行失败 / 已超时
建议状态表:
| 状态 | 含义 |
|---|---|
| Pending | 命令已创建,未发送 |
| Sent | 已发布到 MQTT |
| Received | 控制板已收到 |
| Success | 控制板执行成功 |
| Failed | 控制板执行失败 |
| Timeout | 超时未收到应答 |
| Cancelled | 命令已取消 |
| Expired | 命令已过期 |
对于启动电机、恢复出厂、设置参数等命令,不建议无限重发。必须结合 RequestId、超时、幂等控制和权限审核。
九、Redis、数据库、消息队列如何分工
Redis
用于实时状态,不作为永久业务依据:
-
控制板在线状态;
-
最近心跳时间;
-
最近一次衣架信息;
-
当前执行中的命令;
-
RequestId与应答关联; -
分布式锁;
-
重复消息去重缓存。
MySQL / PostgreSQL
用于永久业务数据:
-
工厂、车间、线体、站位、控制板档案;
-
控制板参数;
-
衣架进出站记录;
-
加工记录;
-
命令执行记录;
-
操作员、工单、权限、审计日志;
-
报警记录。
Kafka 或其他事件流平台
不是一开始就必须上。
当后期存在以下情况时,再增加 Kafka:
-
几万台控制板产生高频数据;
-
要长期保存所有运行事件;
-
要做 BI、设备预测维护、生产节拍分析;
-
多个独立系统都要订阅控制板数据;
-
多工厂数据要汇总到中央平台。
Kafka 的 Topic 可以按分区扩展并设置副本,提高数据流处理与故障恢复能力,但它应作为事件流和数据分析层,不应直接代替吊挂控制命令通道。(Apache Kafka)
十、多工厂时的架构
多个工厂不要全部依赖一个远端 MQTT 集群。
建议每个工厂都有本地 MQTT 与本地业务服务:
工厂 A:本地 Broker 集群 + 本地吊挂业务服务
工厂 B:本地 Broker 集群 + 本地吊挂业务服务
工厂 C:本地 Broker 集群 + 本地吊挂业务服务
↓
中央平台汇总数据
这样即使总部网络、云端网络或 VPN 中断,工厂内部吊挂系统仍能正常运行。
中央平台负责:
-
多工厂设备档案;
-
配置下发;
-
报表与生产统计;
-
软件版本管理;
-
数据分析;
-
跨工厂监控。
工厂本地负责:
-
控制板实时通信;
-
电机启停;
-
衣架进站;
-
加工站处理;
-
面板提示;
-
本地报警;
-
断网后的持续运行。
MQTT Bridge 可用于本地 Broker 与中央 MQTT 平台之间进行跨网络消息同步。(EMQX 文档)
十一、必须做的安全控制
每个控制板不能使用统一账号,例如不能全部使用:
username: hanger
password: 123456
应使用唯一身份:
ClientId: H-F01-L001-S025-000001
控制板权限建议限制为:
允许发布:
Hanger/F01/L001/S025/Up
Hanger/F01/L001/S025/Answer
Terminal/F01/T10025/Notify
允许订阅:
Hanger/F01/L001/S025/Down
禁止:
Hanger/#
Terminal/#
$SYS/#
显示面板权限建议限制为:
允许发布:
Terminal/ToServer
允许订阅:
Terminal/F01/T10025/Notify
禁止发布:
Hanger/#
服务器账号才允许发布:
Hanger/+/+/+/Down
并且“启动电机、恢复出厂、修改参数”等操作必须经过服务器 API、人员权限、工单状态和审计记录校验,不能让后台人员直接使用 MQTT 客户端随意发布。
十二、上线前必须做的压测场景
至少验证以下场景:
-
所有控制板同时上线;
-
大批控制板断线后同时重连;
-
心跳全部集中在同一秒上报;
-
某一线体连续高频过衣架;
-
Broker 节点故障一台;
-
业务服务器故障一台;
-
数据库短时不可用;
-
网络交换机断开后恢复;
-
同一电机命令重复发送;
-
指令过期后控制板重新上线;
-
面板被断网或替换后是否能越权控制吊挂;
-
某控制板不断发送异常或重复数据时是否影响整条线。
最终建议
对于你这个吊挂系统,建议采用:
三节点 MQTT Broker 集群
+ 双机负载均衡
+ 多实例吊挂业务服务
+ Redis 实时状态层
+ MySQL/PostgreSQL 业务数据库
+ MQTT ACL 权限隔离
+ 控制命令唯一 RequestId
+ 控制板业务应答机制
+ 工厂本地自治
+ 中央平台汇总
并保留现有 MQTT 协议作为 V1,同时从新控制板开始逐步切换到按“工厂 / 车间 / 线号 / 站位号”分层的 V2 Topic。这样系统从几百台控制板扩展到数万台时,不需要推倒重做。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)