Broker 写出来以后,真正考验它的不是“演示能不能跑”。
真正考验是现场出了问题时:
你能不能在 5 分钟内判断问题在哪一层。
先给结论:
PLC Broker 排障不要先猜网络,也不要只看客户端日志。
正确方式是按层看:监听层、接入层、CONNECT 解析、订阅表、路由、发送队列、Retain 表、QoS 事务。
一、排障总图

这张图的核心是:
不要一上来就改代码。
先定位层级。
二、连不上怎么查
连不上先看这些变量:
| xRunning | TRUE | Broker 未进入运行态 |
| hListenHandle | 非 0 | TCP 监听未建立 |
| xTcpServerError | FALSE | 监听层错误 |
| xTcpAcceptActive | 连接瞬间可能 TRUE | 有客户端尝试接入 |
| uiAcceptFreeSlot | 非 0 | 有空闲槽位 |
| uiActiveSlotCount | 随连接数变化 | 当前活跃客户端数 |
| aSnapshots[x].xUsed | 连接后保持 TRUE | 槽位是否保住 |
如果这些值在连接过程中不断闪:
xTcpAcceptActive 闪
uiAcceptFreeSlot 闪
uiActiveSlotCount 闪
优先看槽位释放前快照:
| udiLastBytesRead = 0 | 可能首包还没到就释放 |
| udiLastBytesRead > 0 | 已读到 MQTT 报文 |
| xLastConnectParsed = FALSE | CONNECT 解析失败 |
| eLastParseError | 解析失败原因 |
| byLastConnectLevel | 协议级别读取结果 |
如果要在用户程序里做一个最小诊断观察,建议至少把 Broker 实例和快照暴露出来:
// 示例:在线监控时优先观察这些输出,而不是只盯客户端日志。
xBrokerRunning := fbBroker.xRunning;
xBrokerError := fbBroker.xError;
eBrokerError := fbBroker.eLastError;
uiActiveSlotCount := fbBroker.uiActiveSlotCount;
uiAcceptFreeSlot := fbBroker.uiAcceptFreeSlot;
stSlot1Snapshot := fbBroker.aSnapshots[1];
三、CONNECT 失败怎么查
CONNECT 失败最有效的判断表:
| udiLastBytesRead = 0 | TCP 接入有了,但 MQTT 首包未到 |
| sLastProtocolName = MQTT 且 level 4 | MQTT 3.1.1 |
| sLastProtocolName = MQTT 且 level 5 | MQTT 5.0 |
| sLastProtocolName = MQIsdp 且 level 3 | MQTT 3.1 老协议 |
| byLastConnectLevel = 100 | 协议级别偏移错误,读到字符 d |
| MQTT 5.0 连接后断开 | 看 CONNACK 是否返回零属性长度 |
经验结论:
TCP 已读到数据,就不要继续纠结“网线通不通”。
这时问题已经进入 MQTT 报文层。
四、订阅失败怎么查
订阅失败优先看:
| SUBACK 返回码 | 客户端订阅是否被 Broker 接受 |
| uiSubItemCount | 多 Topic 是否全部解析 |
| Topic Filter | 是否合法 |
| ACL 规则 | 是否被权限拒绝 |
| 订阅表 | 是否写入对应槽位 |
快速判断表:
| 客户端直接显示订阅失败 | SUBACK 返回 0x80 |
| 单 Topic 成功,多 Topic 丢项 | 解析循环不完整 |
| device/#/status 失败 | # 位置非法 |
| device/a+ 失败 | + 未独占层级 |
| 订阅成功但收不到 | 路由匹配或订阅表问题 |
五、发布收不到怎么查
发布成功但订阅端收不到,一般分三层:

排查表:
| PUBLISH 解析 | Topic Name、Payload 长度、QoS |
| Router | F_MqttTopicMatch、订阅表 |
| 投递队列 | uiDeliveryQueueCount、队列满计数 |
| TCP 写出 | uiLastTxFrameCount、uiLastTxBytes |
| QoS ACK | TxInflight 状态 |
如果同一主题两个客户端互发,最好先用 QoS0 测通,再测 QoS1 / QoS2。
六、发布延迟怎么查
延迟问题不要靠感觉。
看这些字段:
| uiDeliveryQueueCount 长期大于 0 | 发送出口跟不上 |
| uiProtocolQueueCount 长期大于 0 | 协议响应被拖慢 |
| uiLastTxFrameCount 长期为 1 | 批量写出没生效 |
| uiLastTxFrameCount 常见 1~2 | 小消息批量程度有限,但可能够用 |
| uiMaxDeliveryQueueCountSeen 很高 | 曾出现瞬时堆积 |
当前推荐默认:
cnMaxFramesPerConnectionScan = 8
cnMaxTxFramesPerWrite = 8
cnConnectFirstReadDelayMs = 20
cnConnectionInactiveGraceMs = 3000
通信猫高频崩溃但 MQTTBox 正常时,不要盲目把 Broker 参数继续拉大。
这更像客户端工具承压。
七、Retain 收不到怎么查
Retain 验收必须用“新订阅”测。
| A 发布 CodeSys,Retain=1 | Broker Retain 表数量增加 |
| B 重新订阅 CodeSys | B 立即收到保留消息 |
| A 发布空 Payload,Retain=1 | Broker 清除该 Topic Retain |
| B 再重新订阅 | 不应再收到旧 Retain |
排查变量:
| uiRetainCount | 当前 Retain 数量 |
| sLastRetainTopic | 最近 Retain 命中主题 |
| uiLastRetainPayloadLen | 最近 Retain Payload 长度 |
| Retain 补发队列 | 新订阅是否触发补发 |
八、最常见的 8 个坑
| 以为多个客户端连 1883 是端口冲突 | 这是 Broker 正常模型 |
| 槽位一闪就释放就怀疑网络 | 先看首包等待和 Active 容忍 |
| 只支持 MQTT 协议名 | 还要兼容 MQIsdp |
| MQTT 5.0 CONNACK 少一个零属性长度 | 客户端可能直接断 |
| 订阅表只存字符串 | 必须绑定槽位和 QoS |
| PacketId 直接沿用发布者 | 转发给订阅者要重新分配 |
| Retain 只看发布成功 | 新订阅补发才是真验收 |
| 性能慢就盲目加队列 | 先看批量写帧数和写事务 |
排障结论分级
现场排障最忌讳一句话定罪。Broker 侧至少要把结论分成三类。
| high | TCP 已读到 CONNECT,问题进入 MQTT 解析层 | udiLastBytesRead > 0,且有解析错误 |
| medium | 延迟大概率在发送出口 | 队列水位、uiLastTxFrameCount、客户端时间戳能对上 |
| low | 可能是某个客户端工具承压 | 只有客户端崩溃现象,没有 Broker 错误和抓包 |
Ben 式排障不是把话说满,而是把证据对象钉住。
如果只有客户端日志,没有 PLC 快照和抓包,那最多只能列第一怀疑组;如果 PLC 快照、Broker 诊断和客户端日志三边能对上,结论才可以往 high 提。
九、这一篇你最该记住的 6 句话
下篇预告
主线 8 篇到这里结束。
下一篇是加更:
PLC Broker 要不要完整支持 MQTT 5.0?工业现场别被“新版本”带偏。
我会讲为什么当前轻量 Broker 选择 MQTT 5.0 基础兼容,而不是一上来做完整属性系统。
完整 ST 代码
本篇涉及的完整代码入口:
- MqttBroker/Device/Application/DUTs/ST_MqttBrokerConnectionSnapshot.st
- MqttBroker/Device/Application/DUTs/ST_MqttBrokerDiagItem.st
- MqttBroker/Device/Application/DUTs/ST_MqttBrokerMetrics.st
- MqttBroker/Device/Application/POUs/FBs/FB_MqttBroker.M_LogDiag.st
- MqttBroker/Device/Application/POUs/FBs/FB_MqttBroker.M_ClearDiag.st
- MqttBroker/Device/Application/POUs/FBs/FB_MqttBroker.M_KickClient.st
系列导航
- 系列定位:第 8 篇
- 上一篇:为什么 PLC Broker 会有延迟?从 TCP_Write 一帧一写到批量粘包写出
- 下一篇:加更 1:PLC Broker 要不要完整支持 MQTT 5.0?
项目与资料
- 开源项目名称:MqttBroker
- 前置系列:MqttClient_V2_0
- 核心关键词:现场排障、诊断快照、Retain、连接闪烁、发布延迟
适合谁收藏
- 已经把 Broker 跑起来,但现场问题不断的人
- 需要给同事做 MQTT Broker 排障培训的人
- 想把 PLC 在线变量变成诊断体系的人
- 正在整理产品手册和技术支持文档的人





