2. DDS 基础概念
DDS(Data Distribution Service)是面向实时分布式系统的数据通信中间件标准。它不采用“客户端请求—服务器响应”的中心化模式,而是围绕以数据为中心的发布订阅模型构建。理解 DDS 的五个基础概念——发布订阅模型、域与分区、主题与实例、数据写入者与数据读取者、全局数据空间——是后续掌握 QoS 与可靠通信工程的前提。
一、发布订阅模型:以数据为中心的通信范式
在 DDS 中,通信双方不直接建立连接,而是围绕“数据对象”进行解耦。发布者(Publisher)将数据写入某个主题,订阅者(Subscriber)声明自己关心某个主题,中间件负责按需匹配并投递。这种模型带来三个关键解耦:
- 空间解耦:发布者与订阅者无需知道对方的网络地址或进程标识。
- 时间解耦:双方不必同时在线,DDS 可通过历史缓存与持久化支持迟到订阅者。
- 流解耦:同一份数据可被任意数量的订阅者同时消费,发布者无需为每个消费者单独发送。
与消息队列不同,DDS 的发布订阅是“数据状态”的传播,而非“消息事件”的排队。订阅者最终关心的是某个主题下数据的最新值或历史序列,而不是消息被消费的次数。
二、域与分区:逻辑隔离的两级手段
域(Domain)是 DDS 中最大的逻辑隔离单位。每个域由一个 domainId 标识,不同域之间的实体默认完全不可见,即使运行在同一台机器上。域通常用于隔离不同车辆、不同功能集群或不同安全等级的系统。
分区(Partition)是域内的进一步逻辑划分。发布者和订阅者通过分区名集合进行匹配:只有分区名存在交集时,数据才可能被投递。分区常用于同一域内按功能、按区域或按优先级隔离数据流,例如将“感知数据”和“控制指令”放在不同分区中。
| 隔离手段 | 作用范围 | 匹配依据 | 典型用途 |
|---|---|---|---|
| 域 Domain | 全局最大隔离 | domainId | 不同车型、不同安全域 |
| 分区 Partition | 域内逻辑隔离 | 分区名集合交集 | 感知/控制/诊断数据分流 |
| 主题 Topic | 数据类型与名称匹配 | 主题名 + 数据类型 | 同类数据的发布订阅 |
三、主题与实例:数据组织的两个维度
主题(Topic)是 DDS 中数据发布订阅的基本单位,由“主题名 + 数据类型”共同定义。主题名是字符串标识,数据类型是 IDL 定义的结构体。只有主题名和数据类型都匹配的写入者与读取者才能通信。
实例(Instance)是主题内部的数据分片。一个主题可以包含多个实例,每个实例由数据中的键(Key)字段唯一标识。例如主题“VehicleStatus”以 vehicleId 为键,则每辆车对应一个实例。实例机制让 DDS 能够对同一主题下的不同对象分别维护状态、生命周期和历史缓存。
struct VehicleStatus {
@key long vehicleId; // 键字段,决定实例
double speed;
double battery;
long timestamp;
};
// vehicleId=101 与 vehicleId=102 属于同一主题的不同实例
实例状态包括 ALIVE、NOT_ALIVE_DISPOSED、NOT_ALIVE_NO_WRITERS 等,读取者可以感知某个实例是被显式销毁,还是因为写入者消失而失效。这是 DDS 区别于普通消息中间件的重要能力。
四、数据写入者与数据读取者:通信端点的核心角色
在 DDS 实体层次中,Publisher 管理 DataWriter,Subscriber 管理 DataReader。真正执行数据写入和读取的是 DataWriter 和 DataReader。
- DataWriter:绑定到一个主题,负责将数据样本写入全局数据空间,并携带 QoS 策略控制可靠性、历史、 deadline 等行为。
- DataReader:绑定到一个主题,负责从全局数据空间接收数据样本,并向应用层提供缓存、状态和实例信息。
DataWriter 与 DataReader 之间通过匹配建立关联。匹配条件包括:同一域、主题名一致、数据类型一致、分区名有交集、QoS 兼容。只有匹配成功后,数据才可能被投递。
五、全局数据空间:逻辑上的共享数据池
DDS 将整个域抽象为一个全局数据空间(Global Data Space)。发布者向其中写入数据,订阅者从中读取数据,中间件负责维护这个逻辑空间的一致性。全局数据空间不是一块物理内存,而是一个逻辑视图:每个主题对应空间中的一个“数据通道”,每个实例对应通道中的一个“数据槽”。
全局数据空间的价值在于:它把“谁发给谁”的通信问题,转化为“谁写入了什么、谁读取了什么”的数据问题。这使得系统更容易扩展、替换和动态重组。
六、案例与场景:车载系统中的典型映射
在一辆智能网联汽车中,可以这样映射 DDS 基础概念:
- 域:动力域使用 domainId=0,智驾域使用 domainId=1,两者默认隔离。
- 分区:智驾域内,感知数据放入 partition “perception”,控制指令放入 partition “control”。
- 主题:VehicleStatus、ObstacleList、ControlCmd 等。
- 实例:ObstacleList 以 obstacleId 为键,每个障碍物是一个实例。
- DataWriter/DataReader:感知模块创建 DataWriter 写 ObstacleList,规划模块创建 DataReader 读 ObstacleList。
- 全局数据空间:所有模块通过域内全局数据空间交换数据,无需点对点连接。
七、常见误区与复盘
复盘建议:在设计阶段先画清“域—分区—主题—实例”四级结构,再确定 DataWriter/DataReader 的部署位置和 QoS 需求。基础概念清晰,后续的可靠性、持久性、 deadline 和资源限制才有稳定的落点。