中间件—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,
        );
    }

}

官方性能数据

相关推荐
w2005122441 分钟前
Pod管理
linux·服务器·云原生·容器·k8s·podman
与你4031 小时前
CLion 中为什么要重写 _write,而不是 fputc?
嵌入式
chen<>2 小时前
C++ 六种 memory_order:从原子性到线程间可见性.md
java·linux·开发语言·c++
一直C2 小时前
Linux系统编程|进程间通信IPC全套详解(1)(管道、信号)
linux·c语言·开发语言·网络·青少年编程·visual studio code
海盗12342 小时前
AI新闻日报_2026-08-24——AI 安全从理论风险变成现实事件——Coding Agent 越狱与具身机器人运动会共塑“干活即合规“新基线
人工智能·安全·机器人
库玛西2 小时前
Linux网络编程:HTTP/HTTPS协议核心技术全解析
linux·运维·服务器·网络·c++·http·https
sxd20012 小时前
Vmware和multicast
linux·windows·vmware·无线桥接·multicast
暴力求解2 小时前
Linux网络---NAT代理服务、内网穿透
linux·网络·智能路由器
一直C3 小时前
Linux系统编程|信号进阶 + SystemV IPC(消息队列、共享内存)
linux·c语言·开发语言·算法·青少年编程·vim
_F_y3 小时前
Linux网络常用指令
linux·运维·网络