中间件—zenoh零基础入门

文章目录

基本概念

zenoh是一个开放的协议,与传统协议仅能覆盖单一协议栈层级不同,Zenoh 的设计从微控制器端无缝跨越至多数据中心云部署------全程仅需一套统一的 API,且线路开销仅为 5 字节,其具有以下特点:

  1. 动态数据:基于位置透明的键值表达式实现订阅/发布消息机制。
  2. 静态数据与计算:一种位置透明的查询/可查询抽象层,基于数据库或按需计算,或两者协作,支持地理分布式的查询。

**动态压缩:**头部字段根据实际值动态省略。例如,若没有附件(Attachment)或时间戳,相关字节完全不发送。

**分片机制:**大数据分片,接收端重组,避免大包阻塞小包

数据格式:

rust 复制代码
[ Header (1-2 bytes) ] [ KeyExpr ID (varint) ] [ Payload Length (varint) ] [ Payload ] [ Timestamp (optional) ] [ Attachment (optional) ]

核心

分层设计

传输层之上构建了一层抽象层,支持多协议同时运行。

TCP/UDP、WebSocket、共享内存(当发布和订阅在同机器,自动切换到共享内存,实现零拷贝)

路由算法

Zenoh 使用基于Key Expression Tree的路由表。每个节点维护一个键空间树,当收到数据包时,根据 KeyExpr 的前缀匹配快速转发。支持多路径路由,自动选择延迟最低或带宽最大的路径。

节点分类

Zenoh 节点分为三种角色,可动态切换:

  1. Client (客户端):普通应用节点。
  2. Peer (对等节点):局域网内自动发现,直连通信,无中心依赖。
  3. Router (路由器):负责跨网段、跨云的路由聚合。

Zenoh通信模型

  1. Pub/Sub

发布订阅模式,支持Qos,支持历史数据回放

  1. Query/Reply

请求/响应模式

机制:客户端发送 Get(key),所有匹配该 Key 的 Queryable 节点返回数据。

优势:支持多播查询(一次请求,多个节点回复),天然适合服务发现和配置读取。

场景:读取最新配置、查询设备状态、联邦学习参数聚合。

  1. Storage/Compute(数据存储)

Storage:节点可以声明自己为某个 Key 的"存储器"。即使发布者离线,订阅者仍可从存储器获取最新值或历史序列。

Compute (Downsampling/Aggregation):可以在路由路径上插入"计算插件"。例如,在网关处自动将 100Hz 的传感器数据降采样为 10Hz 再上传云端,无需修改业务代码。

例子

发布端

rust 复制代码
use zenoh::{key_expr::KeyExpr, Config};
use zenoh::bytes::ZBytes;

#[async_std::main]
async fn main() {
    
    // 配置共享内存
    let mut config = zenoh::Config::default();
    config.insert_json5("transport/shared_memory/enabled", "true");
 
   let image_data: Vec<u8> = vec![0; 1920*1080*3];

    // 创建session
    let session = zenoh::open(config).await.unwrap();

    // let bytes = ZBytes::from(image_data);

    let bytes: ZBytes = image_data.into();

    // session.put("example/topic", bytes)
    //         .await
    //         .unwrap();
    session.put("example/topic", "hello world")
            .await
            .unwrap();
}

订阅端:

rust 复制代码
// use zenoh::prelude::*;
use zenoh::{key_expr::KeyExpr, Config};
use zenoh::bytes::ZBytes;
// 声明在编译期把async fn main展开
#[async_std::main]
async fn main() {
    // config::peer() 生成节点配置
    // unwrap() 解包成功拿到session 失败panic
    let session = zenoh::open(Config::default()).await.unwrap();

    let sub = session.declare_subscriber("example/topic")
                                                .await
                                                .unwrap();


    while let Ok(sample) = sub.recv_async().await {

        // |e|转换失败的错误对象
        let payload = sample
            .payload()
            .try_to_string()
            .unwrap_or_else(|e| e.to_string().into());

        println!(
            "Recv {} on {}: {}",
            sample.kind(),
            sample.key_expr().as_str(),
            payload,
        );
    }

}

官方性能数据

相关推荐
草莓熊Lotso2 小时前
【Linux网络】从0手写Reactor反应堆(二):完善核心细节——ET非阻塞读写、分层架构与回调机制
linux·运维·服务器·网络·c++·tcp/ip·架构
mounter6252 小时前
深度解析 eBPF LSM:如何利用 eBPF 构建安全的 Linux 内核纵深防御体系
linux·安全·ebpf·linux kernel·kernel
Brilliantwxx2 小时前
【Linux】 第一个程序终端进度条
linux·运维·服务器
拂拉氏2 小时前
【知识讲解】 Linux漫漫长路的起始--基础命令的了解
linux·命令
AI创界者2 小时前
【网络安全运维】Kali Linux 下 Medusa(美杜莎)工具的高效部署、故障排查与安全测试实战
linux·运维·web安全
FinelyYang3 小时前
CentOS 7.6 自建 LiveKit 部署指南
linux·运维·centos
Huangjin007_3 小时前
【Linux 系统篇(十四)】进程 (二) :PCB、task_struct、fork系统调用
linux·运维·服务器
深念Y3 小时前
hotspot-adb-research
linux·数据库·adb·emmc·随身wifi·移动终端
雨田言炎3 小时前
十、QThread多线程
linux·服务器·开发语言·前端·qt