eclipse-cyclonedds/cyclonedds
GitHub: eclipse-cyclonedds/cyclonedds
Eclipse Cyclone DDS 是 OMG DDS 规范的高性能开源实现,作为 ROS 2 的默认中间件,专注于为分布式实时系统提供低延迟、高吞吐量的发布-订阅通信服务。
Stars: 1206 | Forks: 441

[](https://dev.azure.com/eclipse-cyclonedds/cyclonedds/_build/latest?definitionId=4&branchName=master)
[](https://scan.coverity.com/projects/eclipse-cyclonedds-cyclonedds)
[](https://dev.azure.com/eclipse-cyclonedds/cyclonedds/_build/latest?definitionId=4&branchName=master)
[](https://choosealicense.com/licenses/epl-2.0/)
[](https://choosealicense.com/licenses/edl-1.0/)
[](https://cyclonedds.io)
[](https://discord.gg/BkRYQPpZVV)
# Eclipse Cyclone DDS
Eclipse Cyclone DDS 是 [OMG DDS 规范](https://www.omg.org/spec/DDS/1.4/About-DDS/) 的一个性能非常出色且健壮的开源实现。
Cyclone DDS 是作为 Eclipse IoT 项目完全开放开发的(参见 [eclipse-cyclonedds-dds](https://projects.eclipse.org/projects/iot.cyclonedds)),其[采用者](https://iot.eclipse.org/adopters/?#iot.cyclonedds)名单不断增加(如果您也是其中之一,请添加您的 [logo](https://github.com/EclipseFdn/iot.eclipse.org/issues/new?template=adopter_request.md))。
它是 Robot Operating System [ROS 2](https://docs.ros.org/en/rolling/) 的 Tier-1 中间件。
* [什么是 DDS?](#what-is-dds)
* [入门指南](#getting-started)
* [性能](#performance)
* [配置](#run-time-configuration)
# 什么是 DDS?
DDS 是分布式系统中隐藏得最好的秘密,它的存在时间比大多数发布-订阅消息系统都要长得多,并且仍然胜过许多此类系统。
DDS 被用于各种各样的系统,包括空中交通管制、喷气发动机测试、铁路控制、医疗系统、海军指挥与控制系统、智能温室等等。
简而言之,它在航空航天和国防领域根深蒂固,但已不再局限于此。
而且它很容易使用!
类型通常在 IDL 中定义,并使用 Cyclone 中包含的 IDL 编译器进行预处理,但我们的 [Python 绑定](https://github.com/eclipse-cyclonedds/cyclonedds-python) 允许您即时定义数据类型:
```
from dataclasses import dataclass
from cyclonedds.domain import DomainParticipant
from cyclonedds.core import Qos, Policy
from cyclonedds.pub import DataWriter
from cyclonedds.sub import DataReader
from cyclonedds.topic import Topic
from cyclonedds.idl import IdlStruct
from cyclonedds.idl.annotations import key
from time import sleep
import numpy as np
try:
from names import get_full_name
name = get_full_name()
except:
import os
name = f"{os.getpid()}"
# C、C++ 需要使用 IDL,Python 不需要
@dataclass
class Chatter(IdlStruct, typename="Chatter"):
name: str
key("name")
message: str
count: int
rng = np.random.default_rng()
dp = DomainParticipant()
tp = Topic(dp, "Hello", Chatter, qos=Qos(Policy.Reliability.Reliable(0)))
dw = DataWriter(dp, tp)
dr = DataReader(dp, tp)
count = 0
while True:
sample = Chatter(name=name, message="Hello, World!", count=count)
count = count + 1
print("Writing ", sample)
dw.write(sample)
for sample in dr.take(10):
print("Read ", sample)
sleep(rng.exponential())
```
如今,DDS 在机器人和自动驾驶车辆中也很受欢迎,因为这些系统确实依赖于高吞吐量、低延迟的控制系统,且不会因为中间存在消息代理而引入单点故障。
事实上,它是 ROS 2 中使用最广泛且默认的中间件选择。
它用于在组件之间传输命令、传感器数据,甚至视频和点云。
OMG DDS 规范涵盖了使用发布-订阅消息构建系统所需的一切。
它们定义了一个结构化类型系统,允许在读取器和写入器之间进行自动字节序转换和类型检查。
该类型系统还支持类型演化。
互操作的网络协议和标准的 C++ API 使得构建集成多种 DDS 实现的系统变得容易。
零配置发现也包含在标准中,并受所有实现支持。
DDS 实际上带来了更多:发布-订阅消息是“普通”网络的一个很好的抽象,但单纯的发布-订阅并不影响人们对系统的*思考方式*。
一种非常强大且真正改变了分布式系统视角的架构是“共享数据空间”,这本身是一个古老的想法,实际上就是一个分布式数据库。
大多数共享数据空间设计在实时控制系统中都惨遭失败,因为它们提供了强一致性保证,并牺牲了太多的性能和灵活性。
DDS 的*最终一致*共享数据空间在帮助构建需要满足许多“ility”(可靠性、可维护性、可扩展性、可升级性……)的系统方面非常成功。
说实话,这就是它被发明的原因,而发布-订阅消息仅仅是一种实现技术。
Cyclone DDS 旨在完全覆盖规范,如今已经覆盖了其中的大部分内容。
参考各个 OMG 规范,目前可用内容包括:
- [DCPS](https://www.omg.org/spec/DDS/1.4/PDF) 基础规范
- 零配置发现(如果多播有效)
- 发布/订阅消息
- 可配置的订阅者数据存储
- 许多 QoS 设置 - 活跃性监控、截止时间、历史数据……
- 覆盖范围包括 Minimum、Ownership 和(部分)Content 配置文件
- [DDS Security](https://www.omg.org/spec/DDS-SECURITY/1.1/PDF) - 提供身份验证、访问控制和加密
- [DDS C++ API](https://www.omg.org/spec/DDS-PSM-Cxx/1.0/PDF)
- [DDS XTypes](https://www.omg.org/spec/DDS-XTypes/1.3/PDF) - 结构化类型系统(此处有一些[注意事项](docs/dev/xtypes_relnotes.md))
- [DDSI-RTPS](https://www.omg.org/spec/DDSI-RTPS/2.5/PDF) - 互操作网络协议
Cyclone DDS 中的网络栈已经以某种形式存在了十多年,并在许多系统中证明了自己的价值,包括大型高可用性系统以及需要与其他实现互操作的系统。
本仓库提供了 Cyclone DDS 的核心及其 C API,[OMG C++](https://github.com/eclipse-cyclonedds/cyclonedds-cxx) 和 [Python](https://github.com/eclipse-cyclonedds/cyclonedds-python) 语言绑定位于同级仓库中。
请查阅 [路线图](ROADMAP.md) 以获取即将推出的功能的高级概述。
# 入门指南
## 构建 Eclipse Cyclone DDS
为了构建 Cyclone DDS,您需要一台 Linux、Mac 或 Windows 10 机器(或者,有一些注意事项的话,*BSD、QNX、OpenIndiana 或 Solaris 2.6 也可以),并且主机上安装了以下软件:
* C 编译器(最常见的是 Linux 上的 GCC,Windows 上的 Visual Studio,macOS 上的 Xcode);
* 可选的 GIT 版本控制系统;
* [CMake](https://cmake.org/download/),版本 3.16 或更高;
* 可选的 [OpenSSL](https://www.openssl.org/),我们推荐使用完全修补和支持的版本,但 1.1.1 仍然可以使用;
* 可选的 [Eclipse Iceoryx](https://iceoryx.io) 版本 2.0,用于共享内存和零拷贝支持;
* 可选的 [Bison](https://www.gnu.org/software/bison/) 解析器生成器。缓存源码已检入仓库。
如果您想尝试解析器,则需要安装 bison 解析器生成器。在 Ubuntu 上,`apt install bison` 应该就能完成安装。
在 Windows 上,安装 chocolatey 并执行 `choco install winflexbison3` 应该就能解决问题。在 macOS 上,`brew install bison` 是最简单的方法。
要获取 Eclipse Cyclone DDS,请执行
```
$ git clone https://github.com/eclipse-cyclonedds/cyclonedds.git
$ cd cyclonedds
$ mkdir build
```
根据您是希望使用 Cyclone DDS 开发应用程序还是为其做出贡献,您可以遵循不同的流程:
### 构建配置
除了 `CMAKE_BUILD_TYPE` 等标准选项外,还有一些使用 CMake 定义指定的配置选项:
* `-DBUILD_EXAMPLES=ON`:构建包含的示例
* `-DBUILD_TESTING=ON`:构建测试套件(强制导出库中的所有符号)
* `-DBUILD_IDLC=NO`:禁用 IDL 编译器的构建(影响示例、测试和 `ddsperf` 的构建)
* `-DBUILD_DDSPERF=NO`:禁用用于性能测量的 [`ddsperf`](https://github.com/eclipse-cyclonedds/cyclonedds/tree/master/src/tools/ddsperf) 工具的构建
* `-DENABLE_SSL=NO`:不查找 OpenSSL,移除 TLS/TCP 支持,并避免构建实现身份验证和加密的插件(默认为 `AUTO`,如果找到 OpenSSL 则启用它们)
* `-DENABLE_ICEORYX=NO`:不查找 Iceoryx,禁用 PSMX Iceoryx 插件的构建(默认为 `AUTO`,如果找到 Iceoryx 则启用它)
* `-DENABLE_SECURITY=NO`:不在核心代码中构建安全接口和挂钩,也不构建插件(可以在没有 OpenSSL 的情况下启用安全性,只是在这种情况下您必须从其他地方寻找插件)
* `-DENABLE_LIFESPAN=NO`:排除有限生命周期 QoS 的支持
* `-DENABLE_DEADLINE_MISSED=NO`:排除有限截止时间 QoS 设置的支持
* `-DENABLE_TYPELIB=NO`:排除类型库的支持,还需要使用 `-DENABLE_TYPE_DISCOVERY=NO` 和 `-DENABLE_TOPIC_DISCOVERY=NO` 禁用类型和主题发现
* `-DENABLE_TYPE_DISCOVERY=NO`:排除类型发现和检查类型兼容性的支持(实际上是 XTypes 的大部分内容),还需要使用 `-DENABLE_TOPIC_DISCOVERY=NO` 禁用主题发现
* `-DENABLE_TOPIC_DISCOVERY=NO`:排除主题发现的支持
* `-DENABLE_SOURCE_SPECIFIC_MULTICAST=NO`:禁用源特定多播的支持(禁用此选项和 `-DENABLE_IPV6=NO` 可能是 QNX 构建所需的)
* `-DENABLE_IPV6=NO`:禁用 ipv6 支持(禁用此选项和 `-DENABLE_SOURCE_SPECIFIC_MULTICAST=NO` 可能是 QNX 构建所需的)
* `-DBUILD_IDLC_XTESTS=NO`:包含一组 IDL 编译器测试,这些测试使用 C 后端在(测试)运行时编译 idl 文件,并使用 C 编译器为生成的类型构建测试应用程序,然后执行该程序进行实际测试(不支持 Windows)
* `-DENABLE_QOS_PROVIDER=NO`:禁用 qos provider 的支持
### 面向应用程序开发者
构建和安装使用 Cyclone 开发您自己的应用程序所需的库只需几个简单的步骤。
一方面 Linux 和 macOS,另一方面 Windows,之间存在一些细微差异。
对于 Linux 或 macOS:
```
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX= ..
$ cmake --build .
```
对于 Windows:
```
$ cd build
$ cmake -G "" -DCMAKE_INSTALL_PREFIX= ..
$ cmake --build .
```
其中您应该将 `` 替换为您希望安装 Cyclone DDS 的目录,将 `` 替换为 CMake [生成器](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) 提供的生成构建文件的方式之一。
例如,“Visual Studio 15 2017 Win64”将针对使用 Visual Studio 2017 的 64 位构建。
要在成功构建后安装它,请执行:
```
$ cmake --build . --target install
```
这会将所有内容复制到:
* `/lib`
* `/bin`
* `/include/ddsc`
* `/share/CycloneDDS`
根据安装位置的不同,您可能需要管理员权限。
此时,您已准备好在您自己的项目中使用 Eclipse Cyclone DDS。
请注意,默认构建类型是包含调试信息的发布版本,这通常是应用程序中最方便使用的构建类型,因为它在性能和仍然能够调试事物之间取得了良好的平衡。如果您更喜欢 Debug 或纯 Release 构建,请相应地设置 `CMAKE_BUILD_TYPE`。
### 为 Eclipse Cyclone DDS 做贡献
我们非常欢迎对项目的所有贡献,无论是问题、示例、错误修复、增强功能、文档改进,还是其他任何东西。
在考虑贡献代码时,了解仓库中存在 Azure pipelines 的构建配置,并且有一个使用简单测试框架和 CTest 构建的测试套件可能会有所帮助,如果需要可以在本地构建。
要构建它,请在配置时将 cmake 变量 `BUILD_TESTING` 设置为 on,例如:
```
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON ..
$ cmake --build .
$ ctest
```
## 文档
[文档](https://cyclonedds.io/docs) 仍然相当有限,其中一些部分仍然仅以 `docs` 目录中的文本文件形式提供。
此 README 通常已过时,文档状态正在缓慢改善,因此绝对值得跳过去看一看。
## 构建和运行往返示例
我们将向您展示如何构建和运行一个测量延迟的示例程序。
当您构建 Cyclone DDS 时,示例会自动构建,因此您无需按照这些步骤即可运行该程序,这仅仅是为了说明过程。
```
$ mkdir roundtrip
$ cd roundtrip
$ cmake /share/CycloneDDS/examples/roundtrip
$ cmake --build .
```
在一个终端中,启动将响应 ping 的应用程序:
```
$ ./RoundtripPong
```
在另一个终端中,启动将发送 ping 的应用程序:
```
$ ./RoundtripPing 0 0 0
# payloadSize: 0 | numSamples: 0 | timeOut: 0
# 等待启动抖动稳定
# 预热完成。
# 延迟测量 (单位 us)
# 延迟 [us] 写入访问时间 [us] 读取访问时间 [us]
# 秒数 计数 中位数 最小值 99% 最大值 计数 中位数 最小值 计数 中位数 最小值
1 28065 17 16 23 87 28065 8 6 28065 1 0
2 28115 17 16 23 46 28115 8 6 28115 1 0
3 28381 17 16 22 46 28381 8 6 28381 1 0
4 27928 17 16 24 127 27928 8 6 27928 1 0
5 28427 17 16 20 47 28427 8 6 28427 1 0
6 27685 17 16 26 51 27685 8 6 27685 1 0
7 28391 17 16 23 47 28391 8 6 28391 1 0
8 27938 17 16 24 63 27938 8 6 27938 1 0
9 28242 17 16 24 132 28242 8 6 28242 1 0
10 28075 17 16 23 46 28075 8 6 28075 1 0
```
上述数字是在 2018 年 12 月 12 日运行 4.2 GHz Intel Core i7 的 Mac 上测量的。
从这些数字中,您可以看到往返非常稳定,并且在此硬件上的最小延迟现在已降至 17 微秒(过去是 25 微秒)。
# 性能
可靠的消息吞吐量对于非常小的样本超过 1MS/s,对于 100 字节的样本大约是 GbE 的 90%,在使用 [ddsperf](src/tools/ddsperf) 在两台运行 Ubuntu 16.04 的 Intel(R) Xeon(R) CPU E3-1270 V2 @ 3.50GHz(那是 2012 年的硬件……)之间测量时,延迟约为 30us,可执行文件是在 Ubuntu 18.04 上使用 gcc 7.4.0 为默认(即“RelWithDebInfo”)构建构建的。

这是在订阅者处于监听器模式下,在吞吐量测试中使用异步传递的情况。
该配置是稍微调整过的开箱即用配置:增加了最大消息大小和片段大小,以及写入器端可靠性窗口的高水位标记。
有关详细信息,请参阅 [scripts](examples/perfscript) 目录、[环境详细信息]( ) 以及图表背后的 [吞吐量](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/performance/20190730/sub.log) 和 [延迟](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/performance/20190730/ping.log) 数据。这些还包括 CPU 使用率([吞吐量](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/performance/20190730/throughput-async-listener-cpu.png) 和 [延迟](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/performance/20190730/latency-sync-listener-bwcpu.png)))和 [内存使用](https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/assets/performance/20190730/throughput-async-listener-memory.png)。
# 运行时配置
开箱即用的配置通常应该没问题,但是通过创建具有所需设置的 XML 文件并定义 `CYCLONEDDS_URI` 指向它,可以调整许多选项。
例如(在 Linux 上):
```
$ cat cyclonedds.xml
default
65500B
true
500kB
config
cdds.log.${CYCLONEDDS_PID}
$ export CYCLONEDDS_URI=file://$PWD/cyclonedds.xml
```
(在 Windows 上,必须改用 `set CYCLONEDDS_URI=file://...`。)
此示例显示了以下几点:
* `Interfaces` 可用于覆盖默认选择的接口。
成员包括
* `NetworkInterface[@autodetermine]` 告诉 Cyclone DDS 自动选择它认为最好的接口。
* `NetworkInterface[@name]` 指定要选择的接口名称(上面未显示,autodetermine 的替代方案)。
* `NetworkInterface[@address]` 指定要选择的接口的 ipv4/ipv6 地址(上面未显示,autodetermine 的替代方案)。
* `NetworkInterface[@multicast]` 指定是否应在此接口上使用多播。
默认值 'default' 意味着 Cyclone DDS 将检查操作系统报告的接口标志,并在支持的情况下启用多播。
使用 'true' 忽略操作系统报告的内容并强制启用,使用 'false' 始终禁用此接口上的多播。
* `NetworkInterface[@priority]` 指定接口的优先级。
默认值(`default`)表示普通接口的优先级为 `0`,环回接口的优先级为 `2`。
* `AllowMulticast` 配置将在何种情况下使用多播。
如果选定的接口不支持它,显然不会被使用(`false`);但如果它支持,网络适配器的类型将决定默认值。
对于有线网络,它将使用多播进行初始发现,以及当有多个数据需要发送到的对等点时用于数据(`true`)。
在 WiFi 网络上,它仅将其用于初始发现(`spdp`),因为 WiFi 上的多播非常不可靠。
* `EnableTopicDiscoveryEndpoints` 开启主题发现(假设在编译时已启用),默认情况下它是禁用的,因为它在许多系统中未被使用,并且会带来大量的发现流量开销。
* `Verbosity` 允许控制跟踪,“config”将配置转储到跟踪输出(默认为“cyclonedds.log”,但这里附加了进程 ID)。
使用了哪个接口、使用了什么多播设置等,都在跟踪中。
将详细程度设置为“finest”会提供更多关于内部工作的输出,还有各种其他级别。
* `MaxMessageSize` 控制 RTPS 消息的最大大小(基本上是 UDP 负载的大小)。
诸如此类的大值通常可以提高环回接口上的性能(相对于当前默认值)。
* `WhcHigh` 决定发送器何时等待来自读取器的确认,因为它缓冲了太多未确认的数据。
有一些自动调整,(当前)默认值有点小,无法获得真正的高吞吐量。
有关配置 Cyclone DDS 的背景信息可以在[这里](docs/manual/config.rst)找到,设置列表[可用](docs/manual/options.md)。
# 商标
* “Eclipse Cyclone DDS”、“Cyclone DDS”、“Eclipse Iceoryx”和“Iceoryx”是 Eclipse Foundation 的商标。
* “DDS”是 Object Management Group, Inc. 的商标。
* “ROS”是 Open Source Robotics Foundation, Inc. 的商标。

这是在订阅者处于监听器模式下,在吞吐量测试中使用异步传递的情况。
该配置是稍微调整过的开箱即用配置:增加了最大消息大小和片段大小,以及写入器端可靠性窗口的高水位标记。
有关详细信息,请参阅 [scripts](examples/perfscript) 目录、[环境详细信息](标签:Bash脚本, Cyber-Physical Systems, DDS, Eclipse, Eclipse Cyclone DDS, IoT, OMG标准, ROS 2, Tier-1 Middleware, 中间件, 分布式系统, 发布订阅, 响应大小分析, 安全测试工具, 实时通信, 客户端加密, 嵌入式系统, 工业自动化, 开源, 微服务通信, 数据分发服务, 机器人操作系统, 消息队列, 物联网, 自动驾驶, 逆向工具