跨进程通信使用 Zenoh中间件 进行高效数据传输的测试和分析

文章目录

    • 1. 引言
    • 2. Zenoh C++ 使用指南
      • 2.1 安装 Zenoh C++ 库
      • 2.2 编写基本的 Zenoh C++ 程序
        • 订阅示例
        • 发布示例
      • 2.3 编译和运行程序
    • 3. Zenoh 与 ROS2 集成
      • 3.1 安装 Zenoh
      • 3.2 安装 ROS2 的 Zenoh RMW 实现
      • 3.3 设置 RMW 实现为 Zenoh
      • 3.4 验证配置
    • 4. 编写基于 Zenoh 的 ROS2 应用程序
      • 4.1 发布者节点
      • 4.2 订阅者节点
    • 5. ROS2跨进程通信性能测试
      • 5.1 吞吐量测试 (throughput_in_message_per_second)
      • 5.2 延迟测试 (us)
    • 6. 参考文章

1. 引言

Zenoh 是一个高效的数据传输框架,核心由 Rust 编写,同时提供了 C++、Python 等多种语言绑定。支持多种部署环境和跨网络通信,实现了去中心化的自适应网络发现,最小的协议网络开销,能够满足低延迟和高吞吐量的要求,甚至它内部也实现了IPC(zero copy)。
本文将探讨如何在 C++ 环境下使用 Zenoh 进行数据传输,并讨论 Zenoh 与 ROS2 的集成方式。
跨进程通信使用 Zenoh中间件 进行高效数据传输的测试和分析_第1张图片

2. Zenoh C++ 使用指南

2.1 安装 Zenoh C++ 库

首先,获取并安装 Zenoh C++ 库:

# 获取 zenoh-cpp 库
git clone https://github.com/eclipse-zenoh/zenoh-cpp.git
cd zenoh-cpp

# 安装依赖并构建
mkdir build && cd build
cmake ..
make
sudo make install

2.2 编写基本的 Zenoh C++ 程序

一个基本的 Zenoh C++ 程序包括以下步骤:

  1. 初始化 Zenoh 会话。
  2. 发布或订阅数据。
  3. 处理数据。
订阅示例
#include 
#include 

int main(int argc, char *argv[]) {
    // 初始化 Zenoh session
    auto config = zenoh::Config();
    auto z = zenoh::open(config).res();
    
    // 订阅数据
    auto sub = z->subscribe("/example/key", [](const zenoh::Sample& sample) {
        std::cout << "Received data: " << sample.payload.data() << std::endl;
    });

    // 等待数据
    std::cout << "Waiting for data..." << std::endl;
    std::this_thread::sleep_for(std::chrono::minutes(10)); // 保持运行
    return 0;
}
发布示例
#include 
#include 

int main(int argc, char *argv[]) {
    // 初始化 Zenoh session
    auto config = zenoh::Config();
    auto z = zenoh::open(config).res();

    // 发布数据
    for (int i = 0; i < 10; ++i) {
        std::string message = "Hello Zenoh: " + std::to_string(i);
        z->put("/example/key", message);
        std::cout << "Published: " << message << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    return 0;
}

2.3 编译和运行程序

编译时需要链接 Zenoh 库:

g++ -std=c++17 -o zenoh_example zenoh_example.cpp -lzenoh

然后运行程序:

./zenoh_example

3. Zenoh 与 ROS2 集成

Zenoh 提供了一个轻量级且高效的消息传输机制,能够满足低延迟、高吞吐量的要求。通过 Zenoh 作为 ROS2 的 RMW (ROS Middleware) 实现,开发者可以实现跨网络的高效通信。Zenoh 的架构分为核心通信引擎和不同语言的绑定接口,其中核心由 Rust 编写,C++ 和 Python 绑定则为主流语言提供支持。

在 ROS2 中,使用 Zenoh 的典型步骤包括:

  1. 安装 Zenoh 和 ROS2 的 Zenoh RMW 实现。
  2. 配置 ROS2 使用 Zenoh 作为默认中间件。
  3. 编写基于 Zenoh 的 ROS2 应用程序。

要实现 Zenoh 与 ROS2 的集成,可以按照以下步骤进行详细配置和开发:

3.1 安装 Zenoh

Zenoh 的核心库可以通过以下命令安装:

git clone https://github.com/eclipse-zenoh/zenoh.git
cd zenoh
cargo build --release

Zenoh 的核心是用 Rust 编写的,因此需要安装 Rust 和 Cargo。如果还未安装,可以通过以下命令安装:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

3.2 安装 ROS2 的 Zenoh RMW 实现

ROS2 默认支持多种 RMW(ROS Middleware)实现,Zenoh 也可以作为其中之一使用。你需要安装 rmw_zenohrmw_zenoh_cpp

git clone https://github.com/eclipse-zenoh/zenoh-plugin-dds.git
cd zenoh-plugin-dds
cargo build --release

然后,可以将编译好的库添加到 ROS2 的路径中。

3.3 设置 RMW 实现为 Zenoh

在运行 ROS2 节点时,可以通过以下命令将 RMW_IMPLEMENTATION 设置为 rmw_zenoh_cpp

export RMW_IMPLEMENTATION=rmw_zenoh_cpp

也可以在 .bashrc 文件中添加此命令,以便每次启动终端时自动配置。

3.4 验证配置

通过以下命令验证 Zenoh 是否已作为 ROS2 的默认中间件:

ros2 doctor --report

输出中应显示 RMW_IMPLEMENTATION: rmw_zenoh_cpp

4. 编写基于 Zenoh 的 ROS2 应用程序

在 ROS2 中,你可以按照常规方式编写节点,Zenoh 的集成是透明的。以下是一个使用 Zenoh 的发布者和订阅者示例:

4.1 发布者节点

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

int main(int argc, char *argv[]) {
    rclcpp::init(argc, argv);
    auto node = rclcpp::Node::make_shared("zenoh_publisher");
    auto publisher = node->create_publisher<std_msgs::msg::String>("zenoh_topic", 10);

    rclcpp::WallRate loop_rate(1);
    while (rclcpp::ok()) {
        auto message = std_msgs::msg::String();
        message.data = "Hello from Zenoh Publisher!";
        RCLCPP_INFO(node->get_logger(), "Publishing: '%s'", message.data.c_str());
        publisher->publish(message);
        rclcpp::spin_some(node);
        loop_rate.sleep();
    }
    rclcpp::shutdown();
    return 0;
}

4.2 订阅者节点

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

void topic_callback(const std_msgs::msg::String::SharedPtr msg) {
    RCLCPP_INFO(rclcpp::get_logger("zenoh_subscriber"), "I heard: '%s'", msg->data.c_str());
}

int main(int argc, char *argv[]) {
    rclcpp::init(argc, argv);
    auto node = rclcpp::Node::make_shared("zenoh_subscriber");
    auto subscription = node->create_subscription<std_msgs::msg::String>(
        "zenoh_topic", 10, topic_callback);
    
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

这些节点编写完成后,使用常规的 ROS2 编译工具如 colcon 进行编译:

colcon build

确保在运行时,环境变量 RMW_IMPLEMENTATION 设置为 rmw_zenoh_cpp,然后可以启动发布者和订阅者:

ros2 run <package_name> zenoh_publisher
ros2 run <package_name> zenoh_subscriber

5. ROS2跨进程通信性能测试

为了评估 Zenoh 的性能,我们按照以上方法进行了ROS2跨进程通信的吞吐量和延迟测试,测试数据如下:

5.1 吞吐量测试 (throughput_in_message_per_second)

count 1kb (bytes) 2kb(bytes) 4kb(bytes) 8kb(bytes) 16kb(bytes)
1 258643.170 172798.709 119124.435 90914.272 79555.248
2 261220.364 166884.978 112133.029 87834.264 79053.264
3 252042.470 157376.734 111920.862 96717.972 78143.373
4 276926.169 156251.875 110722.081 89124.870 75229.330
5 261305.844 164742.864 118617.884 98019.081 76151.792
  • 随着消息大小增加,吞吐量逐渐降低。小消息(如1KB)的传输速率最高,约为25万条/秒,而大消息(如16KB)的吞吐量则降至约7.5万条/秒。
  • 消息大小对吞吐量影响显著,较大消息由于传输开销增加,导致吞吐能力下降。

5.2 延迟测试 (us)

count 1kb (us) 2kb(us) 4kb(us) 8kb(us) 16kb(us)
1 67 58 65 64 97
2 96 69 58 71 76
3 82 62 65 63 86
4 68 66 58 71 80
5 104 60 64 62 89
  • 不同消息大小的延迟相对稳定。小消息(如1KB)的延迟在 67-104 微秒之间,而大消息(如16KB)的延迟在 76-97 微秒之间。
  • 延迟随消息大小略有波动,但整体表现较好,能够满足大多数低延迟应用场景的需求。

结论:Zenoh 在跨进程通信中表现出较高的吞吐量和低延迟特性。对于小消息,Zenoh 可以在确保低延迟的同时实现高吞吐量。虽然大消息的吞吐量有所降低,但仍保持了较低的延迟,展示出良好的通信性能。这使得 Zenoh 适合在低延迟和高性能要求的应用中使用,尤其是在分布式系统中。

6. 参考文章

eclipse zenoh 助力雾计算和边缘计算

你可能感兴趣的:(中间件,Zenoh,ROS2,低延迟,分布式,zenoh-cpp)