OPC UA 会话,订阅和超时

本文详细介绍了OPCUA通信中的关键参数,包括SessionTimeout、Timeout、StatusCheckTimeout在维持客户端与服务端连接中的作用。此外,还讨论了订阅的参数,如PublishingInterval、SamplingInterval、KeepAliveCount和LifeTimeCount,以及它们如何影响数据采样和传输。文章强调了正确理解和配置这些参数对于优化OPCUA通信的重要性。

  本文(原文连接:OPC UA Sessions, Subscriptions and Timeouts)中,我将尽力把OPC UA通讯中的各种参数,特别是各种超时参数讲清楚。他们在控制UA 客户端与服务端连接方面很灵活,但每个参数到底起什么作用不是很清楚。

  这里我用的参数名存在于Prosys OPC UA Java SDK 的UaClient 对象,大部分参数名遵循OPC UA规范,也有部分仅与 UaClient 内部行为有关。

Sessions 会话

  所有UA 通讯都通过会话,正常情况下会话需始终活着(alive).客户端和服务端都可以监视会话的状态,以便及早发现问题,做到及时清理,即便会话没有正确关闭。

SessionTimeout 会话超时

  会话不应该很容易超时,因此1个小时是一个不错的默认值。它用来让服务器能关闭失活的会话(比SessionTimeout 更长时间没有收到客户端的任何消息),此时客户端可能已经挂了,或者不再连接。

Timeout(如服务调用超时 service call timeout)

  可以对某个服务调用使用超时,比如连接中断,或者服务器处理时间过长,10秒就ok,但服务端负载重时要延长超时,默认timeout=0表示不启用。

StatusCheckTimeout 状态检测超时

  UaClient通过StatusCheck监视与服务器的连接状态,定时从服务器获取ServerStatus,判断连接是否或者,服务器是否正常。

  你可以使用ServerStatusListener监视状态变更,或者检查ServerStatus或ServerState(ServerStatus中最有用的部分)。

  StatusCheckTimeout独立于默认的Timout,它专门用作定义状态读取的超时,如果发生超时,ServerState的值为CommunicationFault,需要自动或手动重连。

Subscriptions 订阅

  订阅用来定义要从服务器获取的数据,订阅与会话是松耦合的,如果会话超时,订阅可以转给新会话,由UaClient自动完成,可以用几个参数控制订阅。

  最重要的参数是PublishingInterval和SamplingInterval,用来定义数据采样周期,还有定义订阅状态监视的参数。

PublishingInterval 发布周期

  发布周期定义服务端多长时间检查一次订阅是否有新数据需要发给客户端,通常1000毫秒,不应该为-1或0.

  与其使用很小的发布周期,不如使用更小的采样周期。服务端有可能限制最小发布周期。

SamplingInterval 采样周期 和 QueueSize 队列长度

如果想要比发布周期更快记录数据,可以使用采样周期,同时要增加队列长度,这样服务端能够缓存所有数据样本,到发布周期时一次性发给客户端。

KeepAliveCount 保活计数

  如果到发布周期但没有新数据,服务端会跳过但保活次数定义了最多可以跳过多少次,之后哪怕是空消息也要发给客户端,告诉客户的订阅仍然有效,但没数据。

LifeTimeCount 寿命计数

  客户端有责任向服务端发送订阅请求,然后服务端才能发送数据变更通知。服务端通过判断是否有新的请求来判断客户端是否活着。LifeTimeCount定义新请求之前最多允许多少个发布周期,超过后服务端判定客户端失活,清除订阅。

Republish 重发

  通知消息有序号,UaClient可以检测是否有漏掉的消息,如果有,可以发送重发请求让服务端把漏掉的消息再补发,这就要求服务端保存需发送的消息,直到客户端确认收到为止。

提高性能(8月28日新增)

  使用 UA-.NETStandard 开发 OPCUA 客户端时,有两种回调方式,一是给每个 MonitoredItem 的Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs args) 事件加上回调,访问args里面的 NotificationValue属性(MonitoredItemNotification类型)。当订阅数万点时,内存开销会很大,性能不佳。

  在订阅点很多时,推荐使用Subscription上的FastDataChangeCallback 回调来批量获取数据变更的点,仍然能够得到MonitoredItem 和 MonitoredItemNotitfication 两个对象,如下代码中的callback是外部传入的Action。

m_subscription.FastDataChangeCallback = (Subscription subscription, DataChangeNotification notification, IList<string> stringTable) =>
{
	foreach (MonitoredItemNotification itemNotification in notification.MonitoredItems)
	{
		try
		{
			MonitoredItem monitoredItem = subscription.FindItemByClientHandle(itemNotification.ClientHandle); 
			if (monitoredItem == null)
			{
				continue;
			}
			callback(monitoredItem, itemNotification);
		}
		catch (Exception exception)
		{
			Logger.Error(exception, "FastDataChangeCallback 出错", LogSource);
		}
	}
};

丢失订阅问题(待解)

  在项目上使用时遇到个别点数据十几天不刷新,用opcclient测试数据是变的,可能跟参数设置不合理有关。

  PublishingInterval 之前设置为1000,即1秒发布一次,似乎太长了,如果Subscription下的订阅点多,1秒1次要发布的数据可能造成积压,根据网络情况可缩短发布周期,我在局域网改用100ms。

  MaxNotificationsPerPublish 一次发布点数上限,这个参数应与PublishingInterval结合起来,我理解二者的乘积应≥订阅点数*SamplingInterval,才能确保所有数据都能发布出去。

  重复订阅的尝试。 跟踪每个点数据的最后变化时间,当数据不变超过规定时限(如24hr),重新订阅该点。测试发现,90%以上的点都要重新订阅,不知道是不是我连的OPC Server数据变化慢的原因。另外,重新订阅逻辑需要维护点与其对应的Subscription.Key,使得代码逻辑变得复杂。

<think> 我们正在讨论Python OPCUA库的最大订阅数量问题。需要明确的是,OPCUA规范本身对订阅数量没有硬性限制,但实际实现中会受到多种因素影响,包括服务器配置、客户端资源(内存、CPU)网络条件等。 在Python OPCUA库中,默认配置可能无法满足高订阅需求,但可以通过调整参数优化。关键参数包括`max_subscriptions`(控制最大订阅数)`max_monitored_items_per_sub`(控制每个订阅下的监控项数量)。 具体操作如下: 1. 服务器端配置:创建服务器时可通过`server.set_security_policy``server.set_security_IDs`设置安全策略,同时通过`server.set_max_subscriptions`调整最大订阅数限制。 2. 客户端配置:创建客户端后,使用`set_max_subscriptions`方法调整订阅上限,但需注意该值不能超过服务器端设置。 示例代码展示了如何在客户端设置最大订阅数: ```python from opcua import Client client = Client("opc.tcp://localhost:4840") client.set_max_subscriptions(50) # 将最大订阅数设为50 client.connect() ``` 实际限制需参考具体硬件环境网络状况测试确定。建议通过压力测试寻找系统瓶颈。 相关问题: 1. 如何监控管理Python OPCUA订阅资源? 2. Python OPCUA订阅与监控项有何区别? 3. 如何优化Python OPCUA订阅性能? </think> 在 Python `opcua` 库中,**订阅数量没有绝对的硬性上限**,但实际限制主要受以下因素影响: ### 📌 核心限制因素 1. **服务器配置** OPC UA 服务器端通常通过参数限制最大订阅数(如 `maxSubscriptions`),Python 客户端无法超过此限制。 *例如:KEPServerEX 默认 1000 个订阅,Ignition 默认 500 个[^1]* 2. **客户端资源** 每个订阅需维护独立线程缓存队列,订阅过多会导致: - 内存消耗剧增(每个订阅约 1-10MB) - CPU 占用飙升(通知处理线程阻塞) - Python GIL 竞争加剧 3. **网络带宽** 高频数据更新时,订阅数增加会指数级提升网络负载,可能触发超时断连。 --- ### ⚙️ Python 客户端配置建议 通过调整客户端参数优化: ```python from opcua import Client client = Client("opc.tcp://server:4840") client.set_security_string("Basic256Sha256,SignAndEncrypt,cert.pem,key.pem") # 关键配置参数 client.settings.session_timeout = 60_000 # 会话超时(ms) client.settings.max_subscriptions = 100 # 最大订阅数(建议值) client.settings.max_notifications_per_publish = 1000 # 单次发布最大通知数 client.connect() ``` --- ### 性能测试建议 1. **渐进式压力测试** ```python subscriptions = [] for i in range(150): # 逐步增至系统崩溃临界点 sub = client.create_subscription(publishing_interval=100, priority=1) sub.subscribe_data_change(items) # 添加监控项 subscriptions.append(sub) monitor_memory_usage() ``` 2. **监控指标**: - `psutil.Process().memory_info().rss`(内存占用) - 网络延迟(Wireshark 抓包分析) - 服务器日志中的拒绝请求记录 --- ### 🚀 优化策略 1. **合并订阅** 将同频率的监控项合并到更少订阅中 2. **降低采样频率** 非关键数据延长 `publishing_interval` 3. **使用批处理** 通过 `subscribe_data_change()` 单次注册多个节点 ```python sub.subscribe_data_change([node1, node2, node3]) # 1个订阅3个节点 ``` > 💡 经验值:普通服务器配置下,Python 客户端通常可稳定支持 **50-200 个订阅**,具体需实测验证[^2]。 --- ### 📚相关问题 1. 如何诊断 Python OPCUA 订阅性能瓶颈? 2. OPC UA 订阅与轮询(read)的性能对比有何差异? 3. 如何在 Python 中实现订阅失败的重连机制? [^1]: OPC UA 规范 Part 4 - Services, Section 5.13.2 (Subscription Management) [^2]: Python-opcua 官方文档 - Client Subscription 配置参数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值