register_nodes / unregister_nodes
register_nodes 把客户端常用的 NodeId 注册到服务端, 服务端返回临时高效 NodeId
(生命周期 = Session). 后续 read / write / MonitoredItem 用这个临时 ID 比原始
NodeId 快得多 (服务端跳过完整 NodeId 解析).
适用判断
- 单次脚本 → 不需要
- 长期运行高频访问相同节点 → 强烈推荐
- 大规模 SCADA 1000+ Tag 持续监控 → 必须
签名
pub fn Session::register_nodes(&self, node_ids: &[&str])
-> Result<Vec<String>, OpcUaError>;
pub fn Session::unregister_nodes(&self, registered_node_ids: &[&str])
-> Result<StatusCode, OpcUaError>;
用法
// 1. 应用启动时注册
let orig = [
"ns=2;s=Plant.Line1.Sensor.Temperature",
"ns=2;s=Plant.Line1.Sensor.Pressure",
"ns=2;s=Plant.Line1.Sensor.FlowRate",
];
let temp = s.register_nodes(&orig)?;
// temp 现在是服务端给的临时 ID, 类似 ["i=99001", "i=99002", "i=99003"]
// 2. 后续高频访问用临时 ID (快得多)
for _ in 0..10000 {
let dv = s.read(&temp[0])?;
let _ = dv.variant().try_get_f64().unwrap_or(0.0);
}
// 3. 应用退出前释放
let temp_refs: Vec<&str> = temp.iter().map(String::as_str).collect();
s.unregister_nodes(&temp_refs)?;
何时用
| 场景 | 必要性 |
|---|---|
| 单次脚本, 100 个节点 | 低 (省的开销可忽略) |
| 长期运行, 高频访问相同节点 | 高 (省时显著) |
| 大规模 SCADA, 1000+ Tag 持续监控 | 必须 |
性能数据
服务端 NodeId 解析的耗时取决于实现:
- 数字 NodeId (
i=2258) 通常 O(1) 哈希查找 — register_nodes 收益小 - 字符串 NodeId 长路径 (
ns=2;s=Plant.Line1.Sensor.Temperature) — 服务端可能 O(n) 字符串解析, register_nodes 收益大 (典型 30-50% 加速)
RAII 包装 (推荐)
Rust 用 RAII 自动 unregister 是惯用法:
use darra_opcua::{Session, OpcUaError};
pub struct RegisteredNodes<'s> {
session: &'s Session,
pub ids: Vec<String>,
}
impl<'s> RegisteredNodes<'s> {
pub fn new(s: &'s Session, originals: &[&str]) -> Result<Self, OpcUaError> {
let ids = s.register_nodes(originals)?;
Ok(Self { session: s, ids })
}
}
impl<'s> Drop for RegisteredNodes<'s> {
fn drop(&mut self) {
let refs: Vec<&str> = self.ids.iter().map(String::as_str).collect();
let _ = self.session.unregister_nodes(&refs);
}
}
// 用法
{
let reg = RegisteredNodes::new(&s, &["ns=2;s=A", "ns=2;s=B"])?;
for _ in 0..1000 {
let _ = s.read(®.ids[0])?;
}
} // <- 离开作用域自动 unregister
错误
| 错误 | 原因 |
|---|---|
BAD_NODE_ID_UNKNOWN | 某个原始 NodeId 不存在 (整体 RPC 仍可能成功, 该项返回空字符串) |
BAD_TOO_MANY_OPERATIONS | 单次注册数量超过服务端上限 (典型 1000) |
DARRA_INVALID_ARGUMENT | 输入含 NUL 字符 |
注意
- 注册的临时 ID 只在当前 Session 有效, Disconnect 后失效
- Session 重连后 (
transfer_subscriptions) 临时 ID 通常仍有效, 但保险起见重新 Register - 不释放的临时 ID 会随 Session 关闭自动 GC, 但显式 unregister 是好习惯