3. PubSub核心概念
OPC UA PubSub 把传统客户端/服务器模式中“请求—响应”的耦合关系拆开,改为以消息为中心的数据分发模型。理解 PubSub,关键不是记住几个名词,而是看清一条数据从信息源到消费端之间经过了哪些角色、被如何组织、按什么节奏发送、在什么条件下失效。本节围绕发布者、订阅者、消息代理、数据集、数据集字段、发布间隔与生存时间七个核心概念展开,它们共同决定了 PubSub 通信的实时性、可靠性与可维护性。
一、核心角色:发布者、订阅者与消息代理
发布者(Publisher)是数据的生产与发送方。它通常位于现场设备、PLC、边缘网关或数据采集服务中,负责从地址空间、过程变量或内部缓存中采集数据,按照配置的编码方式(如 UADP 或 JSON)封装成网络消息,并通过 UDP、MQTT、AMQP 等传输协议发出。发布者不关心谁在接收,也不为某个特定客户端维护会话,它只负责“按时把数据放到网络上”。
订阅者(Subscriber)是数据的消费方,可以是 SCADA、MES、历史数据库、边缘分析服务或另一个控制器。订阅者通过加入组播组、订阅 MQTT 主题或连接 AMQP 队列来接收消息,然后按照约定的数据集元数据解析字段。订阅者同样不需要与发布者建立点对点连接,因此一个发布者可以同时服务大量订阅者,扩展性显著优于传统轮询。
消息代理(Broker)是 MQTT 或 AMQP 场景中的中间转发节点。它接收发布者投递的消息,再根据主题或队列规则分发给订阅者。代理的存在带来了解耦:发布者和订阅者不必同时在线,也不必知道对方地址。但代理也引入了额外跳数和排队延迟,因此在硬实时场景中,很多系统会选择无代理的 UDP 组播方式,让发布者直接向网络发送数据。
二、数据组织:数据集与数据集字段
数据集(DataSet)是发布者对外提供的一组逻辑数据集合,可以理解为“一帧消息里打包了哪些变量”。一个发布者可以同时发布多个数据集,例如一个数据集用于高频过程值,另一个数据集用于低频状态与诊断信息。数据集本身不规定传输协议,它描述的是内容结构。
数据集字段(DataSetField)是数据集中的最小数据单元。每个字段通常包含名称、数据类型、值以及可选的状态码和时间戳。字段可以来自 OPC UA 地址空间中的变量节点,也可以来自发布者内部计算得到的派生值。订阅者依据数据集元数据(DataSetMetaData)来理解字段顺序和类型,因此元数据与数据消息必须保持一致,否则会出现解析错位。
下面是一个典型的数据集配置片段,展示了一个包含温度、压力和设备状态的数据集:
DataSetName: Line1ProcessData
Fields:
- Name: Temperature
Type: Double
Source: ns=2;s=Line1.Temp
- Name: Pressure
Type: Float
Source: ns=2;s=Line1.Press
- Name: DeviceState
Type: Int32
Source: ns=2;s=Line1.State
PublishingInterval: 100 ms
三、时间控制:发布间隔与生存时间
发布间隔(PublishingInterval)决定发布者多久发送一次数据集。它直接决定了数据的新鲜度和网络负载:间隔越小,实时性越高,但带宽和 CPU 消耗也越大;间隔越大,网络越轻松,但订阅者看到的数据可能已经过时。发布间隔通常以毫秒为单位配置,并且可以针对不同数据集分别设置。
生存时间(TimeToLive,TTL)是消息或数据的有效期。它回答的是“这条数据在多长时间内仍然可信”。在 MQTT 中,TTL 可以体现为消息过期时间;在 OPC UA PubSub 的订阅侧,生存时间常用来判断是否已经太久没有收到新数据,从而触发超时、告警或降级处理。发布间隔与生存时间需要配合设置:TTL 通常应大于发布间隔的若干倍,以容忍偶发的网络抖动和丢包。
| 概念 | 作用 | 典型取值/形式 | 设置不当的后果 |
|---|---|---|---|
| 发布者 | 采集并发送数据 | PLC、网关、边缘服务 | 发送过快导致拥塞,过慢导致数据陈旧 |
| 订阅者 | 接收并解析数据 | SCADA、MES、数据库 | 解析错位、漏收、重复处理 |
| 消息代理 | 转发与解耦 | MQTT Broker、AMQP Queue | 增加延迟,配置错误导致消息丢失 |
| 数据集 | 组织一组变量 | Line1ProcessData | 字段混杂,难以维护和扩展 |
| 数据集字段 | 最小数据单元 | Temperature、Pressure | 类型不一致导致解析失败 |
| 发布间隔 | 控制发送节奏 | 100 ms、1 s | 过小浪费带宽,过大失去实时性 |
| 生存时间 | 判断数据是否仍可信 | 300 ms、5 s | 过小误告警,过大无法及时发现断流 |
四、案例场景:一条产线数据的发布与消费
假设某产线需要把温度、压力和设备状态以 100 ms 的间隔发布给监控系统和历史库。发布者运行在边缘网关上,配置一个数据集 Line1ProcessData,包含三个字段。传输方式选择 UDP 组播,因为局域网内多个订阅者需要同时接收且要求低延迟。监控系统订阅该组播地址,按元数据解析字段;历史库同样订阅,但只按秒级批量入库。
此时发布间隔为 100 ms,生存时间设置为 300 ms。如果监控系统连续 300 ms 没有收到新消息,就判定为数据断流并触发告警。这样既不会因为一次丢包就误报,也能在真正断流时快速响应。若网络出现抖动,订阅者可能收到重复或乱序消息,因此解析逻辑需要结合序列号和时间戳进行判断,而不是简单覆盖。
五、常见误区与复盘
- 把发布间隔当成端到端延迟。发布间隔只决定发送频率,实际延迟还包括采集、编码、网络传输、代理排队和订阅者处理时间。
- 忽略数据集元数据版本。发布者修改字段后,订阅者若仍使用旧元数据,会出现字段错位或类型错误。
- TTL 设置过小。网络轻微抖动就会触发大量超时告警,反而掩盖真实故障。
- 所有数据共用一个数据集。高频与低频数据混在一起,会导致不必要的带宽消耗和解析负担。
- 认为 Broker 一定可靠。Broker 只负责转发,持久化和重传策略需要额外配置,否则仍可能丢消息。
把七个概念串起来看:发布者按发布间隔把数据集发送出去,数据集由若干数据集字段组成;消息可以经过消息代理转发,也可以直接到达订阅者;订阅者解析字段,并用生存时间判断数据是否仍然可信。只有这些参数彼此匹配,PubSub 才能在实时性、带宽和可靠性之间取得平衡。