订阅自恢复
概述
Session 重连后, 服务端 Subscription 可能仍存活也可能已被清理。SDK 两步走:
- transferSubscriptions — 把旧 SubscriptionId 转给新 Session
- Recreate — 转移失败时, 用本地缓存的 MonitoredItemSpec 重建 Sub + 全部 MI
业务侧无需手动处理。
API
| 方法 / 事件 | 类别 | 读写 | 说明 |
|---|---|---|---|
| ua.transferSubscriptions(oldSubIds, sendInitialValues) | 方法 | 写 | 转移订阅 |
| events.onSubscriptionLost(...) | 事件 | 读 | 订阅丢失 |
| events.onSubscriptionRestored(...) | 事件 | 读 | 订阅恢复 |
代码示例
import com.darra.opcua.*;
import java.util.List;
try (DarraOpcUa ua = new DarraOpcUa("opc.tcp://localhost:4840")) {
ua.events().onSubscriptionLost(e ->
logger.warn("订阅丢失: subId=" + e.subscriptionId));
ua.events().onSubscriptionRestored(e ->
logger.info("订阅已恢复: " + e.source));
ua.connect();
// 创建 sub + MI, 全程不变
OpcUaSubscription sub = ua.createSubscription(500);
long mi = sub.add("ns=2;s=Temp", AttributeId.Value, 200,
MonitoringMode.Reporting, 10, true,
DataChangeFilter.builder()
.deadbandType(DeadbandType.ABSOLUTE).deadbandValue(0.5).build());
sub.addDataChangedListener(args ->
System.out.println(args.value.value + " @ " + args.value.sourceTimestamp));
// 拔网线 30 秒, 看日志:
// reconnecting → reconnected → subscriptionRestored
// 数据自动续上, filter 也保留
// 手动 transfer
List<StatusCode> rcs = ua.transferSubscriptions(
List.of(sub.getSubscriptionId()), true);
}
恢复流程
重连成功
↓
对每个本地 Subscription:
1. transferSubscriptions(oldSubId)
├─ Good → subscriptionRestored 事件
└─ BadSubscriptionIdInvalid → 进入 2
2. createSubscription(originalParams) 拿新 subId
3. 按本地 _miCache 重建所有 MI
- SamplingInterval / Mode / QueueSize / DiscardOldest
- DataChangeFilter
- EventFilter
- Triggering Links
4. subscriptionRestored 事件
缓存的字段
_miCache 保留: NodeId / AttributeId / SamplingInterval / Mode / QueueSize / DiscardOldest / DataChangeFilter / EventFilter。
恢复时全部重放, 服务端 mi id 会变, 业务侧应使用 clientHandle 而非 server-side id 对账。
最佳实践
- 业务用 clientHandle, 不要持久化 mi id
- 监听 subscriptionRestored 事件
- 不要在 subscriptionLost 里手动 recreate, SDK 已经在做
- 关键参数变更后 pause 再 resume
跨语言对照
| C# | Python | Java | C++ | Rust | C |
|---|---|---|---|---|---|
| TransferSubscriptions | transfer_subscriptions | transferSubscriptions | TransferSubscriptions | transfer_subscriptions | DarraUa_Session_TransferSubscriptions |