DDS Topic 本身不支持运行时内容过滤,真正起作用的是 DataReader 级的 QueryCondition 配合 read_with_condition;Partition 才是跨域隔离主力,通过字符串标签在发现阶段硬隔离。

DDS Topic 过滤靠 read_with_condition 或 take_w_condition?错,Topic 本身不支持运行时过滤
Topic 是 DDS 数据类型的逻辑容器,定义了数据结构(IDL)、QoS(如可靠性、持久性)和唯一名称。它不承担内容过滤职责——你不能在 create_topic 时传入 SQL 式条件,也不能靠改 Topic 名称来筛数据。
真正起作用的是 DataReader 级别的过滤机制,而 Topic 只负责“这个数据长什么样、发给谁”。常见误解是以为换个 Topic 名(比如加后缀 _urgent)就能隔离业务流,其实这只是命名约定,没强制隔离效果。
- Topic 名重复会触发
TOPIC_ALREADY_EXISTS_ERROR,但不同 Topic 间完全无通信约束 - 同一 Topic 下所有
DataReader默认收全量数据,无论Writer发什么实例 - 想按内容字段过滤(比如只收
status == 1),必须用QueryCondition+read_w_condition,且需提前在DataReader上启用DATA_READER_HISTORY_QOS
Partition 过滤才是跨域/跨模块隔离的主力手段
Partition 是 DomainParticipant 和 Publisher/Subscriber 级的字符串标签,DDS 内核在组网阶段就做匹配:只有 Publisher 和 Subscriber 的 partition 列表有交集,它们的 Topic 流量才可能互通。这是轻量、高效、无需序列化开销的硬隔离。
典型场景是微服务拆分或测试环境隔离:一个 Domain 里跑 dev/test/prod 多套逻辑,靠 partition 字符串天然隔开,比建多个 Domain 节省资源。
立即学习“C++免费学习笔记(深入)”;
- 设置方式统一走
set_qos:对Publisher用PARTITION_QOS_POLICY,值为std::vector<:string>{"backend"}</:string> -
Subscriber同样设PARTITION_QOS_POLICY,值为{"backend", "shared"}→ 它能收两个分区的数据 - 空分区(
{""}或未设置)等价于通配,会匹配所有非空分区,但不匹配其他空分区(不同实现略有差异,别依赖) - 分区名区分大小写,且不能含
/、.、空格等特殊字符,否则部分 RMW 层(如 Cyclone DDS)会静默截断或报PRECONDITION_NOT_MET_ERROR
Topic + Partition 组合使用的实际约束
Topic 和 Partition 不是叠加过滤器,而是正交维度:Topic 定义“发什么”,Partition 定义“发给谁”。两者组合才能构成完整路由策略,但要注意底层实现的兼容性边界。
比如你在 Connext DDS 里设 Topic="sensor" + Partition={"v2"},同时另一端用 Partition={"v1","v2"},能通;但换到 Fast DDS 2.10+,若 Partition 值含下划线(如 "v2_internal"),可能因正则解析 bug 导致匹配失败,日志只报 no matching writers,不提示分区问题。
- 避免在 Partition 中嵌入动态信息(如 PID、时间戳),会导致发现风暴和内存泄漏
- 同一个
DomainParticipant下,不同Publisher可用不同 Partition,但所有Subscriber共享同一份 Partition 配置(除非显式为每个Subscriber单独 set_qos) - Topic 名长度受
DomainParticipant的resource_limits.max_topic_name_length限制(默认 512),而 Partition 总长度受max_partitions和单个字符串长度共同约束(Cyclone DDS 默认单个 partition ≤ 256 字符)
调试时最常卡住的三个点
90% 的“收不到数据”问题不是代码写错,而是发现阶段就断连。别急着查 take 返回值,先确认底层是否握手成功。
- 用
rtiddsspy(Connext)或dds perf-test(Fast DDS)抓实时发现包,看Publisher和Subscriber的partition字段是否一致显示在输出里 - 检查
DomainParticipant的transportQoS:如果用了UDPv4但网络禁 multicast,partition 匹配成功也传不了数据,此时on_subscription_matched回调仍会触发,造成“已连接”假象 - 在
DataReaderListener::on_data_available里打日志前,先调get_matched_publications,返回空说明根本没发现 Writer——这时再回头查 partition 拼写、大小写、Domain ID 是否一致
Partition 是字符串匹配,不是正则,也不支持通配符。想实现“backend*”这种需求,得靠多注册几个明确的 partition,或者换用 ContentFilter + QueryCondition,但后者代价高得多。



















