3. OPC UA 通信模型:客户端/服务器架构、发布/订阅模式、会话与安全通道

好,咱们进入第三章。这一章讲的是OPC UA的通信模型,说白了就是数据怎么在设备之间流动的。我见过不少工程师,配置了半天连不上,其实就是没搞懂这几个基础模型的关系。

3.1 客户端/服务器架构:最经典的玩法

OPC UA最基础的通信方式,就是客户端/服务器架构。你想想看,一个PLC作为服务器,把数据暴露出来;一个上位机作为客户端,去读取这些数据。这就是最典型的场景。

核心特点:

  • 主动请求:客户端发起请求,服务器响应。说白了就是「你问我答」。
  • 连接导向:需要建立稳定的TCP连接。我在项目中遇到过,有些现场网络不稳定,客户端频繁断连,结果数据采集全乱了。
  • 适合点对点:一个客户端对一个服务器,或者少量客户端对少量服务器。

重要概念:在OPC UA里,客户端和服务器不是物理设备的概念,而是逻辑角色。同一个设备可以既是客户端又是服务器。比如一个边缘网关,它作为服务器给上层系统提供数据,同时作为客户端去采集下层PLC的数据。

实际应用场景:

  • SCADA系统读取PLC数据
  • MES系统与设备通信
  • HMI画面实时刷新

3.2 发布/订阅模式:解决大规模通信的痛点

客户端/服务器模式有个硬伤——当你有几百个客户端同时要数据时,服务器扛不住。我做过一个项目,一个车间里50多个工位都要读取同一台机器人的状态,结果服务器CPU直接飙到90%。

这时候就需要发布/订阅模式了。它的思路很简单:

  • 发布者:只管把数据扔到「消息中间件」里,不管谁在收
  • 订阅者:只管从消息中间件里拿数据,不管谁在发
  • 消息中间件:负责转发,可以是一台专门的Broker服务器

为什么说它好?

  • 解耦:发布者和订阅者不需要知道对方的存在
  • 可扩展:加一个订阅者,发布者完全无感
  • 一对多:一份数据可以同时发给N个订阅者

我的经验:发布/订阅模式特别适合「数据分发」场景。比如一个温度传感器,它的数据要同时发给监控系统、报警系统、历史数据库。用客户端/服务器模式,传感器得同时维护三个连接;用发布/订阅模式,它只管发一次就行。

OPC UA PubSub的实现方式:

  • UDP多播:适合局域网,延迟低,但不保证可靠
  • MQTT桥接:适合跨网络,支持QoS,我比较推荐这种方式
  • AMQP:适合企业级消息队列,功能强大但配置复杂

3.3 会话与安全通道:通信的「握手」与「加密」

嗯,这里要注意。OPC UA的通信不是裸奔的,它有一套完整的握手和加密机制。我见过有人直接把安全模式设成None,结果被客户骂得狗血淋头。

安全通道(Secure Channel):

  • 建立在TCP连接之上
  • 负责加密通信内容
  • 使用证书进行身份验证
  • 有生命周期,到期需要重新建立

会话(Session):

  • 建立在安全通道之上
  • 代表一个逻辑连接
  • 包含用户身份信息(用户名密码、证书等)
  • 管理订阅、节点浏览等操作

避坑指南:我曾经犯过一个错误——把安全通道的超时时间设得太短。结果客户端每隔几分钟就要重新握手,导致数据采集出现间隙。后来我改成30分钟,问题就解决了。记住:安全通道超时时间要大于会话超时时间,否则会话会被强制断开。

安全模式对比:

安全模式 加密 签名 适用场景
None 测试环境,不推荐生产
Sign 需要验证身份,不关心数据加密
SignAndEncrypt 生产环境,强烈推荐

3.4 三种模型的配合使用

实际项目中,这三种模型不是互斥的,而是配合使用的。我举个例子:

  1. 现场层:PLC作为服务器,边缘网关作为客户端,使用客户端/服务器模式采集数据
  2. 中间层:边缘网关作为发布者,把数据发布到MQTT Broker
  3. 上层:多个监控系统作为订阅者,从Broker获取数据

你看,这样既保证了现场通信的实时性,又解决了上层多系统数据分发的问题。

关键点:安全通道和会话是OPC UA通信的基础设施。不管用客户端/服务器还是发布/订阅,都离不开这两个概念。我建议你在配置时,先把安全通道调通,再建立会话,最后才去配置数据读写或订阅。

配置示例(伪代码):

// 1. 创建安全通道
SecureChannel channel = new SecureChannel();
channel.setSecurityMode(SecurityMode.SignAndEncrypt);
channel.setCertificate(clientCertificate);
channel.connect(serverEndpoint);

// 2. 创建会话
Session session = new Session(channel);
session.setIdentityToken(new UserNameIdentityToken("admin", "password"));
session.activate();

// 3. 读取数据
DataValue value = session.read(nodeId);

好了,这一章就到这里。下一章我们会讲OPC UA的地址空间与节点模型,到时候你会看到数据在服务器里是怎么组织的。有什么问题,欢迎在课程群里讨论。