当前位置: 首页 > news >正文

第6篇_Retain_Will_KeepAlive_工业现场为什么不能只会转发PUBLISH

一个 Broker 会转发 PUBLISH只能说明它能跑通“实时消息”。但工业现场还会问新客户端上线后能不能马上拿到设备当前状态设备异常掉线其他客户端能不能收到通知客户端死了不发包Broker 会不会一直占着槽位这三个问题对应Retain、Will、KeepAlive。先给结论只会转发 PUBLISH 的 Broker只能算半个 Broker。工业现场要的是状态可恢复、异常可感知、死连接可清理。但这里的 Retain、Will、KeepAlive 仍然服务于小型工业现场不等同于带数据库持久化、集群复制和离线会话恢复的大型 Broker。一、Retain 解决“最后值”问题假设 PLC 发布Topic: line1/plc/status Payload: RUN Retain: TRUE后来 HMI 才上线并订阅line1/plc/status如果 Broker 支持 RetainHMI 应该立刻收到RUN。如果不支持HMI 只能等下一次发布。Retain 生命周期Retain 表不是消息队列。一个 Topic 只保存最后一条保留消息。二、Retain 的操作表操作Broker 行为Retain0 发布正常路由不写 Retain 表Retain1 且 Payload 非空写入或覆盖该 Topic 的 RetainRetain1 且 Payload 为空清除该 Topic 的 Retain新订阅命中 RetainSUBACK 后补发保留消息Topic Filter 命中多个 Retain按预算逐条补发现场最常见误区客户端勾选 Retain 发布成功不代表 Broker 已经实现 Retain。真正的验收方法是客户端 A 对CodeSys发布一条 Retain 消息。客户端 B 重新连接并订阅CodeSys。B 应该立即收到这条消息。三、Will 解决异常离线问题Will 是客户端在 CONNECT 时提前交给 Broker 的遗嘱消息。如果客户端异常断线Broker 代替它发布 Will。关键区别断开方式是否触发 Will客户端发送 DISCONNECT否KeepAlive 超时是TCP 异常断开是协议错误导致关闭通常是这在工业现场非常有用。比如device/plc01/online offline如果 Will 再配合 Retain就能让新上线的 HMI 也看到“最后离线状态”。四、KeepAlive 解决死连接问题MQTT KeepAlive 不是“定时发心跳”这么简单。它是客户端和 Broker 对连接存活的约定如果在 KeepAlive 时间内没有任何控制报文客户端应该发 PINGREQBroker 收到后回 PINGRESP。Broker 判断超时时通常按 1.5 倍宽限如果客户端声明KeepAlive 60Broker 不应该 60 秒一到就立刻杀。工业网络有抖动1.5 倍宽限更稳。五、Retain / Will / KeepAlive 三者会汇合这三个功能不是孤立的。这也是为什么 Broker 不能只在连接 FB 里“关掉 TCP”就结束。异常关闭可能会触发 Will。Will 可能会更新 Retain。Retain 更新后还要路由给订阅者。六、ST 代码入口代码入口作用FB_MqttBrokerRouter.M_UpdateRetain写入、覆盖或清除 Retain 表FB_MqttBrokerRouter.M_FindNextRetain新订阅时查找匹配 RetainFB_MqttBroker.M_ServiceConnections检查连接状态、KeepAlive、异常清理FB_MqttBroker.M_HandlePublish处理普通发布和 Retain 更新ST_MqttBrokerRetainedMessageRetain 表项结构Retain 更新逻辑大概是IF stPublish.xRetain THEN fbRouter.M_UpdateRetain( sTopicName : stPublish.sTopicName, pPayload : stPublish.pPayload, uiPayloadLen : stPublish.uiPayloadLen, eQoS : stPublish.eQoS); END_IFKeepAlive 检查逻辑大概是udiTimeoutMs : TO_UDINT(uiKeepAliveSec) * 1500; IF (udiNowMs - udiLastActivityMs) udiTimeoutMs THEN xNeedClose : TRUE; xNeedPublishWill : xWillEnabled; END_IF七、现场排障表现象优先检查可能原因Retain 勾选后新订阅收不到uiRetainCount、sLastRetainTopic没写 Retain 表或没做订阅补发Retain 清不掉Payload 长度是否为 0清除规则未实现正常断开也发 Will是否收到 DISCONNECT正常断开标志没设置异常断开不发 WillCONNECT 是否解析 WillWill 字段没保存客户端死了还占槽位udiLastActivityMsKeepAlive 未检查或宽限过大模型边界与验证路径Retain、Will、KeepAlive 看起来是三个功能点往上看其实是会话生命周期模型。功能解决的边界验证路径RetainTopic 最后状态由谁保存新客户端订阅后是否立即收到最后值Will异常离线由谁声明拔掉客户端或异常断开后是否发布 WillKeepAlive死连接由谁清理停止客户端发送后是否按 1.5 倍宽限清理结论分级结论可信度边界Retain 必须通过新订阅补发验证high只看发布成功不够正常 DISCONNECT 不应触发 Willhigh这是 MQTT 会话语义KeepAlive 超时要结合扫描周期和网络抖动设置medium不同 PLC 任务周期和客户端行为会影响观测结果这里先不要把 Retain 理解成持久化数据库。当前轻量 Broker 保存的是 PLC 内存中的最后值断电、下载或工程重启后的行为要按实际工程配置重新验证。八、这一篇你最该记住的 5 句话Retain 解决新订阅者获取主题最后值的问题。Will 解决异常离线通知问题。KeepAlive 解决死连接清理问题。正常 DISCONNECT 不应该触发 Will。Retain、Will、KeepAlive 最后都会回到 Broker 的路由和连接清理调度里。下篇预告下一篇讲性能优化。重点是为什么 PLC Broker 会有明显延迟以及为什么从“一帧一写”改成“批量粘包写出”能明显改善实时性。完整 ST 代码本篇涉及的完整代码入口MqttBroker/Device/Application/POUs/FBs/FB_MqttBrokerRouter.M_UpdateRetain.stMqttBroker/Device/Application/POUs/FBs/FB_MqttBrokerRouter.M_FindNextRetain.stMqttBroker/Device/Application/POUs/FBs/FB_MqttBroker.M_ServiceConnections.stMqttBroker/Device/Application/DUTs/ST_MqttBrokerRetainedMessage.st系列导航系列定位第 6 篇上一篇PUBLISH 不是收到就转发Broker 怎么处理 QoS、PacketId 和多客户端 fanout下一篇为什么 PLC Broker 会有延迟从 TCP_Write 一帧一写到批量粘包写出项目与资料开源项目名称MqttBroker前置系列MqttClient_V2_0核心关键词Retain、Will、KeepAlive、最后值、异常离线适合谁收藏Retain 发布成功但新订阅收不到的人想用 MQTT 表示设备在线离线状态的人正在处理客户端死连接的人想把 Broker 从“能转发”提升到“现场可用”的人
http://www.gsyq.cn/news/1410048.html

相关文章:

  • 第4篇_SUBSCRIBE不是存个字符串_Broker怎么维护订阅表通配符和多客户端路由
  • 如何零费用享受全套现代化 IT 基础设施的终极流程
  • Win11Debloat:3分钟完成Windows 11终极优化与深度清理的免费神器
  • 新手教程:5分钟实现一个智能体
  • 别再混淆了!一文讲透FPGA中Standard FIFO与FWFT(预读)FIFO的核心差异与应用选型
  • 安全攻防 - 04 GMSSL 工程介绍
  • 终极FPDF指南:5分钟学会用纯PHP生成专业PDF文档
  • 从STK到osgEarth:我的雷达可视化方案迁移踩坑全记录(附完整C++代码)
  • Ambari 3.0+Kafka安全认证
  • Python RTSP 视频流处理完全指南:从稳定接收到智能分析
  • Vue项目里用Highcharts+Canvas做实时频谱瀑布图,我是怎么解决30ms渲染不卡顿的?
  • UE4植被动态效果避坑指南:从SimpleGrassWind撕裂到完美风场(含顶点绘制替代方案)
  • 手把手教你学Simulink——考虑器件结温特性的双向DC-AC逆变器热管理建模仿真
  • 告别纸上谈兵:用Wireshark抓包实战解析5G N2/NGAP切换全流程(附pcap文件)
  • 从保险理赔到广告效果分析:不懂公式也能上手的‘置信区间’实战指南
  • 别再让求解器‘装傻’:COMSOL事件接口(显示/隐式)避坑指南与典型场景盘点
  • 从pnpm报错到Vite打包优化:手把手解决JeecgBoot-Vue3项目启动与构建的那些坑
  • 面试官:Agent 落地会遇到哪些坑?
  • 语言脑机接口解码流程对比【脑机接口恢复语言2】
  • 避坑指南:为什么你的Conda环境里LabelMe的转换命令总失效?详解Python包管理与路径冲突
  • 从‘打包’到‘解压’:一次搞懂tar命令的-cvf、-xvf、-cvzf、-zxvf在CentOS/Ubuntu下的实战
  • 手机变Linux开发机:用Termux和MT管理器打造移动端代码编辑与文件管理环境
  • 架构师的底层重构逻辑:面部松弛、纹路加深?用3大核心参数选对高阶胶原饮
  • C++入门刷题记录~(动态内存分配)
  • NestJS项目接口权限怎么管理?结合Swagger文档清晰展示JWT守卫与角色控制
  • Claude_Desktop——全流程指南-免登录-DeepSeek-中文汉化
  • 第10章:AI辅助安全审计实战——从漏洞检测到形式化验证
  • 烤火罩在潮湿环境容易发霉吗 新 E 选品牌源头厂家说明
  • Claude Code + DeepSeek V4 Pro +VS Code 安装
  • 别再傻傻分不清!SystemVerilog Interface里modport和clocking到底谁管谁?