4. OPC UA 通信模式:请求/响应模式、订阅与监控项机制

OPC UA 客户端与服务器之间的数据交互主要依赖两种通信模式:请求/响应(Request/Response) 与 订阅(Subscription)。前者适用于一次性查询或配置操作,后者则用于高效、实时的数据变化推送。理解这两种模式及其核心组件——监控项(MonitoredItem),是构建高性能数据采集系统的关键。

4.1 请求/响应模式

请求/响应模式是 OPC UA 最基本的通信方式,遵循“一问一答”的同步或异步调用模型。客户端发送一个请求(Request)到服务器,服务器处理完成后返回一个响应(Response)。

  • 适用场景:读取变量当前值、写入属性、浏览地址空间、调用方法、历史数据查询等一次性操作。
  • 通信特点:简单直接,可靠性高;但频繁轮询会占用大量网络带宽和服务器资源,不适合高频数据采集。
  • 典型服务:Read、Write、Browse、Call、HistoryRead。
性能提示:在仪表盘实时刷新场景中,若使用请求/响应模式轮询(例如每 100ms 调用一次 Read),当监控点数超过 1000 时,网络延迟和 CPU 占用会显著上升。此时应优先考虑订阅模式。

4.2 订阅(Subscription)模式

订阅模式是一种发布/订阅(Pub/Sub)机制的变体,由客户端创建订阅,并在订阅下添加监控项。服务器按照客户端设定的采样间隔和发布间隔,主动将数据变化推送给客户端,无需客户端反复请求。

4.2.1 核心概念与流程

  1. 创建订阅(CreateSubscription):客户端定义发布间隔(PublishingInterval)和订阅生命周期参数。
  2. 添加监控项(CreateMonitoredItems):在订阅下指定要监控的节点(NodeId)、采样间隔(SamplingInterval)和过滤条件(如数据变化触发、死区设置)。
  3. 数据推送(Publish):服务器按发布间隔将变化的数据打包成通知消息(NotificationMessage),通过 Publish 响应发送给客户端。
  4. 修改/删除:客户端可动态调整监控项参数或移除监控。
关键参数:
采样间隔(SamplingInterval):服务器读取底层数据源的最小时间间隔。
发布间隔(PublishingInterval):服务器将累积的变化数据打包发送给客户端的时间间隔。
通常建议 SamplingInterval ≤ PublishingInterval,以避免数据丢失。

4.2.2 订阅模式与请求/响应模式对比

对比维度 请求/响应模式 订阅模式
通信触发方式 客户端主动发起 服务器主动推送
网络负载 高(频繁轮询) 低(仅推送变化数据)
实时性 取决于轮询间隔 取决于发布间隔,延迟更低
适用数据量 少量、低频 大量、高频
典型服务 Read, Write, Browse CreateSubscription, Publish

4.3 监控项(MonitoredItem)机制

监控项是订阅模式的核心单元,它定义了“监控什么”以及“如何触发通知”。每个监控项绑定到一个具体的节点(如变量节点),并包含采样、过滤和通知规则。

4.3.1 监控项属性

  • NodeId:被监控节点的唯一标识。
  • AttributeId:监控的属性(通常为 Value)。
  • SamplingInterval:采样周期(毫秒)。
  • Filter:数据变化过滤器(DataChangeFilter)或事件过滤器(EventFilter)。
  • QueueSize:通知消息队列大小,防止数据丢失。
  • DiscardOldest:队列满时是否丢弃最旧的数据。

4.3.2 数据变化过滤器(DataChangeFilter)

用于控制哪些数据变化会触发通知,避免无效传输:

触发条件(Trigger) 说明
StatusValue 值或状态码发生变化时触发
Status 仅状态码变化时触发
Value 仅数值变化时触发(忽略状态)

此外,可设置死区(Deadband):绝对值死区(Absolute)或百分比死区(Percent),只有当数值变化超过死区范围时才推送,有效过滤噪声。

4.4 通信模式与监控项协作关系

下图展示了客户端与服务器之间,订阅模式与监控项如何协同工作:

OPC UA 订阅模式与监控项协作流程 订阅模式与监控项协作流程 OPC UA 客户端 CreateSubscription CreateMonitoredItems Publish (循环) 处理 Notification OPC UA 服务器 创建 Subscription 创建 MonitoredItem 采样 & 过滤 发送 Notification 监控项(MonitoredItem) 定义采样间隔、过滤条件、队列策略

4.5 实际应用建议

  • 仪表盘实时数据:使用订阅模式,设置 PublishingInterval = 200ms,SamplingInterval = 100ms,配合绝对值死区(如 0.5%)过滤噪声。
  • 历史数据查询:使用请求/响应模式中的 HistoryRead 服务,指定时间范围与聚合方式(如平均值、最大值)。
  • 大规模监控:将监控项分散到多个订阅中,避免单个订阅负载过高;合理设置 QueueSize 防止网络抖动导致数据丢失。
常见陷阱:
1. 采样间隔设置过小(如 10ms)可能导致服务器 CPU 满载,建议根据数据源实际变化频率调整。
2. 忘记设置死区会导致大量微小变化触发通知,增加网络和客户端处理负担。
3. 订阅超时(PublishingInterval 内未收到 Publish 请求)会导致服务器删除订阅,需客户端定期发送 Publish 请求保持连接。

4.6 代码示例:创建订阅与监控项(C# 伪代码)

// 创建订阅
var subscription = new Subscription
{
    PublishingInterval = 200,   // 200ms 发布一次
    MaxNotificationsPerPublish = 1000,
    Priority = 100,
    LifetimeCount = 1000,
    MaxKeepAliveCount = 10
};
session.AddSubscription(subscription);
subscription.Create();

// 创建监控项
var monitoredItem = new MonitoredItem
{
    StartNodeId = new NodeId("ns=2;s=Temperature.Sensor1"),
    AttributeId = Attributes.Value,
    SamplingInterval = 100,   // 100ms 采样一次
    QueueSize = 10,
    DiscardOldest = true,
    Filter = new DataChangeFilter
    {
        Trigger = DataChangeTrigger.StatusValue,
        DeadbandType = (uint)DeadbandType.Absolute,
        DeadbandValue = 0.5
    }
};
subscription.AddItem(monitoredItem);
monitoredItem.Notification += (item, args) =>
{
    // 处理数据变化通知
    var value = args.MonitoredItem.LastValue;
    Console.WriteLine($"收到数据: {value}");
};