2. DDS基础概念
DDS(Data Distribution Service,数据分发服务)是一套面向实时分布式系统的数据通信中间件标准。它最核心的思想不是“客户端请求服务器”,而是以数据为中心的发布订阅模型:参与者不直接互相调用,而是围绕“主题”这一数据对象进行读写,由中间件负责把数据从写入者高效、可靠地分发到所有感兴趣的读取者。理解发布订阅模型以及数据写入者、数据读取者、主题、域、分区这些术语,是掌握 DDS 工程实践的第一步。
一、发布订阅模型的基本工作原理
在 DDS 中,通信双方被抽象为发布者(Publisher)和订阅者(Subscriber)。发布者通过数据写入者(DataWriter)把样本写入某个主题,订阅者通过数据读取者(DataReader)从该主题获取样本。中间件根据主题名称、数据类型和 QoS(服务质量)策略,自动完成匹配与传输,无需应用层关心对端地址、连接建立或重连逻辑。
这种模型的关键特征是:时间解耦(发布者与订阅者不必同时在线)、空间解耦(双方不需要知道彼此位置)、同步解耦(读写操作异步进行)。因此它非常适合雷达、飞控、车载、工业控制等对实时性和动态拓扑要求高的场景。
应用写入数据 → DataWriter → Publisher → 域内传输 → Subscriber → DataReader → 应用读取数据
二、核心术语逐项解析
域(Domain)是 DDS 中最大的逻辑隔离单位。每个域由一个域 ID 标识,只有处于同一域内的参与者才能互相发现和通信。不同域之间的数据完全隔离,常用于把不同业务、不同安全等级或不同测试环境分开。
主题(Topic)是数据的逻辑名称,由“主题名 + 数据类型”共同确定。发布者和订阅者必须使用相同的主题名和兼容的数据类型才能匹配。主题是 DDS 中数据流动的“地址”,也是 QoS 策略绑定的对象。
数据写入者(DataWriter)是发布端实际执行写操作的实体。应用调用 write() 把样本交给 DataWriter,DataWriter 再根据 QoS 决定缓存、重传、丢弃或按历史深度保存。一个 Publisher 可以管理多个 DataWriter。
数据读取者(DataReader)是订阅端实际执行读操作的实体。它从中间件接收样本,应用通过 take() 或 read() 获取数据。其中 take() 会移除样本,read() 只读取不移除,这是初学者最容易混淆的一点。
分区(Partition)是域内更细粒度的逻辑分组机制。通过给发布者和订阅者设置相同的分区字符串,可以控制哪些读写者能够互相匹配。分区常用于同一域内按功能、优先级或数据敏感度做二次隔离。
三、典型场景:一个温度监控系统
假设一个机房温度监控系统,需要把多个温度传感器的数据实时分发给监控大屏和告警服务。可以这样设计:
- 域 ID 使用
0,表示生产环境;测试环境使用域 ID1,互不干扰。 - 主题定义为
MachineRoom/Temperature,数据类型为Temperature,包含设备编号、温度值、时间戳。 - 每个传感器对应一个 DataWriter,分区设置为
"sensor"。 - 监控大屏和告警服务各创建一个 DataReader,分区同样设置为
"sensor",从而只接收传感器数据。
// 伪代码:创建主题与数据写入者
Topic<Temperature> topic = participant.create_topic("MachineRoom/Temperature");
Publisher publisher = participant.create_publisher();
DataWriter<Temperature> writer = publisher.create_datawriter(topic);
Temperature sample;
sample.device_id = "T-001";
sample.value = 26.5;
writer.write(sample);
// 订阅端
DataReader<Temperature> reader = subscriber.create_datareader(topic);
reader.take(sample); // 读取并移除
四、常见误区与复盘要点
误区二:忽略数据类型匹配。主题名相同但数据类型不一致时,读写者无法匹配,通信会静默失败。排查时应优先检查类型注册与主题名。
误区三:混淆 read 与 take。
read() 只读取不移除,take() 读取后移除。若循环中一直用 read(),可能反复处理同一条样本。误区四:分区设置不一致。发布者与订阅者分区不匹配时,即使主题相同也无法通信。分区是“与”关系,必须至少有一个共同分区。
五、核心术语速查表
| 术语 | 英文 | 作用 | 关键点 |
|---|---|---|---|
| 域 | Domain | 最大逻辑隔离单位 | 域 ID 不同则完全隔离 |
| 主题 | Topic | 数据逻辑名称与寻址入口 | 名称 + 数据类型必须一致 |
| 数据写入者 | DataWriter | 发布端写数据实体 | 由 Publisher 管理 |
| 数据读取者 | DataReader | 订阅端读数据实体 | 由 Subscriber 管理 |
| 分区 | Partition | 域内二次逻辑分组 | 读写者需有共同分区 |
| 服务质量 | QoS | 控制可靠性、历史、时限等 | 不兼容会导致匹配失败 |