1. 核心线程架构全景
1.1 全局线程架构全景图
Fast-DDS 3.6.x采用分层并发模型,将计算密集型与IO密集型操作解耦,支持通过ThreadSettings QoS配置所有线程属性:
graph TB
subgraph DomainParticipantThreadPool["DomainParticipant Thread Pool"]
E["Event Thread: dds.ev.<participant_id>"] -->|"定时调度"| TE["TimedEvent队列: Heartbeat/Nack/KeepAlive"]
AW["Async Writer Thread: dds.asyn.<pid>.<idx>"] -->|"流量控制"| FC["FlowController: FIFO/RR/Priority"]
DS["Discovery Server Event: dds.ds_ev.<participant_id>"] -->|"数据库同步"| DB["Discovery DB: PDP/EDP同步"]
SL["Security Logging: dds.slog.<participant_id>"] -->|"审计日志"| SEC["SecurityManager"]
end
subgraph TransportLayer["Transport Layer Threads"]
RUDP["Reception UDP: dds.udp.<port>"] -->|"recvmsg"| MSG["RTPS Message解析"]
RTCP["Reception TCP: dds.tcp.<port>"] -->|"stream read"| MSG
RSHM["Reception SHM: dds.shm.<port>"] -->|"segment监听"| MSG
TKA["TCP Keep Alive: dds.tcp_keep"] -->|"心跳检测"| CONN["TCP连接状态"]
WSHM["SHM Watchdog: dds.shm.wdog"] -->|"健康监控"| SEG["共享内存段清理"]
end
subgraph BackgroundServices["Background Services"]
LOG["Logging Thread: dds.log"] -->|"异步消费"| LOGQ["Log队列"]
DSH["Datasharing Listener: dds.dsha.<id>"] -->|"零拷贝通知"| DR["DataReader"]
end
MSG -->|"触发回调"| E
FC -->|"批量发送"| RUDP
TE -->|"触发"| AW
技术细节:2. Library Overview - 3.6.0
• 线程命名规范:3.6.x引入标准化线程命名(dds.{type}.{id}),便于调试和性能分析
• Event Thread:基于asio::io_service的事件循环,处理周期性事件(默认1ms精度),通过ResourceEvent类实现
1.2 异步写处理流程(ASYNCHRONOUS_PUBLISH_MODE)
当配置异步发布模式时,写操作解耦为入队-调度-发送三阶段:
sequenceDiagram
participant User as User Thread
participant DW as DataWriter
participant FC as FlowController<br/>/Priority/RR/FIFO
participant AW as AsyncWriterThread<br/>dds.asyn.*
participant Trans as Transport Layer
User->>DW: write(data)
DW->>DW: 序列化+加密(Security)
alt ASYNCHRONOUS模式
DW->>FC: add_new_sample(change)<br/>入队待发送
FC->>FC: 令牌桶计算<br/>max_bytes_per_period/period_ms
FC-->>User: 立即返回OK<br/>(非阻塞)
loop AsyncWriterThread::run()
AW->>FC: get_next_change()<br/>调度策略选择
FC-->>AW: CacheChange_t*
AW->>Trans: send_data()<br/>实际网络IO
Trans-->>AW: 发送结果
AW->>DW: 触发Listener回调<br/>on_publication_matched
end
else SYNCHRONOUS模式
DW->>Trans: 直接send_data()<br/>用户线程上下文
Trans-->>User: 阻塞返回
end
关键技术实现(src/cpp/rtps/resources/AsyncWriterThread.cpp):
| 机制 | 实现细节 | 源码参考 |
|---|---|---|
| 唤醒机制 | condition_variable + mutex,3.6.x引入AsyncInterestTree优化感兴趣写者集合 | GitHub Discussion #2456 |
| 流量整形 | 基于FlowController的令牌桶算法,支持4种调度策略:FIFO、ROUND_ROBIN、HIGH_PRIORITY、PRIORITY_WITH_RESERVATION | 15.5. Large Data Rates - 3.6.0 |
| 批量发送 | RTPSMessageGroup聚合多个小样本,减少系统调用;受max_bytes_per_batch限制 | /home/guang/code/opensource/Fast-DDS/src/cpp/rtps/messages/RTPSMessageGroup.cpp |
1.3 ResourceEvent 定时器架构
Event Thread是Fast-DDS的中枢神经系统,管理所有时间触发逻辑:
flowchart TD
A[ResourceEvent::run<br/>dds.ev.*] --> B{asio::io_service::run_one}
B -->|超时/事件| C[process_event]
C --> D{事件类型}
D -->|定时到期| E[TimedEvent::trigger<br/>虚拟函数]
D -->|异步IO就绪| F[传输层回调<br/>TCP/SHM]
D -->|用户定时| G[Listener::on_trigger]
E --> H[重新计算expiry_time]
H --> I[asio::steady_timer::expires_at<br/>堆结构管理]
I --> B
subgraph "TimedEvent派生类实例"
PH[PeriodicHeartbeat<br/>StatefulWriter]
NR[NackResponseDelay<br/>重传抑制]
PL[WriterLiveliness<br/>保活检测]
RP[ResendParticipantData<br/>发现重传]
end
E --> PH
E --> NR
E --> PL
E --> RP
style A fill:#f9f,stroke:#333,stroke-width:2px
style I fill:#bbf,stroke:#333,stroke-width:2px
技术细节:
- 定时精度:使用
asio::steady_timer(单调时钟),避免系统时间回拨影响 - 线程安全:
ResourceEvent类在3.6.x中已移至src/cpp目录(非公开API),通过TimedEventImpl管理生命周期 - 优先级:支持通过
ThreadSettings配置线程优先级、CPU亲和性、堆栈大小
2. 适用场景与注意事项
2.1 场景适配指南
| 场景 | 推荐配置 | 线程关注重点 | 风险点 |
|---|---|---|---|
| 高吞吐发布 | ASYNCHRONOUS_PUBLISH_MODE + 自定义FlowController(FIFO/RR) | 监控dds.asyn.* CPU占用,避免流控令牌不足导致队列膨胀 | 异步队列堆积导致内存溢出;需配置max_bytes_per_period |
| 低延迟通信 | SYNCHRONOUS_PUBLISH_MODE + 禁用Nagle算法 | 关注dds.ev.*调度延迟,避免心跳定时器抖动 | 用户线程阻塞影响业务;大消息序列化耗时 |
| 大规模节点 | 增大Event Thread优先级,启用Discovery Server | dds.ds_ev.*成为瓶颈,需监控数据库锁竞争 | 发现风暴导致线程饥饿;需配置max_bytes_per_period限制Builtin流量 |
| 共享内存传输 | SHM Transport + 独立Watchdog | 注意dds.shm.wdog对segment异常的清理 | 僵尸共享内存段残留;Windows平台SHM端口竞争 |
| RPC服务 | 自定义RpcServerSchedulingStrategy(线程池模式) | thread_pool_size配置影响并发处理能力 | 直接调度策略(Direct)可能导致栈溢出;feed参数处理需谨慎 |
2.2 关键注意事项
线程死锁风险:
3.6.x之前版本AsyncWriterThread在DomainParticipant析构时可能出现condition_variable销毁顺序问题(先销毁锁后销毁条件变量导致hang),3.6.x通过Semaphore和ResourceEvent重构修复Previous end-of-life versions - 3.6.0
• 禁止在Listener回调中调用阻塞API:Event Thread执行Listener回调时,阻塞操作会延迟所有定时事件处理
CPU亲和性与实时性:
• 通过ThreadSettingsQoS可配置:
thread_settings.set_scheduler_priority(60); // Linux实时优先级
thread_settings.set_affinity({0, 2}); // 绑定CPU核心
thread_settings.set_stack_size(4096*1024); // 8MB栈空间
• MacOS限制:3.3.1修复了线程亲和性设置为0的问题 Previous end-of-life versions - 3.6.0
内存与资源管理:
• Datasharing Listener:每DataReader独立线程(dds.dsha.*),零拷贝场景下线程数随Reader线性增长,需监控线程资源消耗
• Security Logging:独立线程(dds.slog.*),启用Security时需额外考虑日志队列内存
诊断命令:
# 查看Fast-DDS线程实时状态
gdb -p $(pgrep your_app) -ex "info threads" -ex "thread apply all bt" --batch
# 3.6.x特有:检查FlowController队列堆积
# 在FlowControllerImpl::get_next_change()打断点,观察unsent_changes_.size()
3. 参考数据源
3.1 官方文档与规范
| 数据源类型 | 链接/标识 | 说明 |
|---|---|---|
| 官方文档 | Fast DDS 3.6.0 Library Overview - Threading Model | 权威线程类型与命名规范定义 |
| FlowController配置指南 | Large Data Rates - Flow Controllers | 流量控制策略与配置示例 |
| RPC线程调度 | Customizing RPC Server request scheduling | 服务端线程池与调度策略 |
| 迁移指南 | Migration Guide to Fast DDS v3 | 3.x线程类API变更(ResourceEvent等移至internal) |
3.2 源码实现参考(基于用户本地路径)
| 组件 | 源码路径 | 关键类/函数 |
|---|---|---|
| 异步写线程 | /home/guang/code/opensource/Fast-DDS/src/cpp/rtps/resources/AsyncWriterThread.cpp | AsyncWriterThread::run(), add_flow_controller() |
| 流量控制器 | /home/guang/code/opensource/Fast-DDS/src/cpp/rtps/flowcontrol/ | FlowControllerImpl, SchedulerPolicy枚举 |
| 事件系统 | /home/guang/code/opensource/Fast-DDS/src/cpp/rtps/resources/ResourceEvent.cpp | ResourceEvent::run(), TimedEvent基类 |
| 线程设置 | /home/guang/code/opensource/Fast-DDS/src/cpp/fastdds/core/thread_settings/ | ThreadSettingsQoS, apply_thread_settings() |
| 传输层接收 | /home/guang/code/opensource/Fast-DDS/src/cpp/rtps/transport/ | UDPChannelResource, SharedMemChannelResource |
| 日志线程 | /home/guang/code/opensource/Fast-DDS/src/cpp/fastdds/log/ | Log::run()(dds.log线程) |
3.3 社区与学术讨论
| 类型 | 链接 | 内容摘要 |
|---|---|---|
| 架构讨论 | GitHub Discussion #2456: Multithreading architecture | 社区关于Reception线程数量、AsyncWriterThread生命周期的技术讨论 |
| ROS2集成 | Configuring Fast DDS in ROS 2 | RMW层线程配置与RMW_FASTRTPS_PUBLICATION_MODE环境变量 |
| 版本发布说明 | Previous versions - 2.13.0 | ThreadSettingsQoS首次引入版本(2.13.0)及后续修复 |
3.4 专利与技术渊源 • DDS标准: OMG DDS Specification v1.4 (线程模型符合DDS规范的并发要求)
• RTPS协议: OMG RTPS 2.5 (Real-Time Publish-Subscribe) - 事件驱动架构基于RTPS状态机实现
• Asio库: Fast-DDS底层使用Boost.Asio (Eprosima内部实现eprosima::fastdds::rtps::AsioServiceTie封装)
3.5 总结
该线程模型通过职责分离(IO与计算分离)、资源隔离(每DomainParticipant独立Event Loop)、背压机制(FlowController限流),支撑了从嵌入式设备到云端服务的全场景DDS通信需求。3.6.x版本的关键改进在于全线程可配置性(ThreadSettingsQoS覆盖所有线程类型)和FlowController粒度细化(支持Builtin Writers流量控制)。