iT邦幫忙

2025 iThome 鐵人賽

DAY 30
0
Rust

30 天玩轉 Zenoh:Rust 助力物聯網、機器人與自駕的高速通訊系列 第 30

Day 30: 三十天的 Zenoh 旅程:從好奇到深入,我們學到了什麼?

  • 分享至 

  • xImage
  •  

三十天的 Zenoh 旅程:從好奇到深入,我們學到了什麼?

還記得第一次接觸 Zenoh 時的疑惑嗎?「又一個訂閱發佈的通訊協定?它跟 MQTT、DDS、Kafka 有什麼不同?」三十天過去了,我們不僅找到了答案,更發現了一個連接萬物的全新視角。

讓我們回顧這段精彩的探索之旅。

旅程的起點:為什麼是 Zenoh?

在第一週,我們提出了一個關鍵問題:為什麼機器人和 IoT 領域需要 Zenoh?

答案逐漸清晰:

  • MQTT 很輕量,但效能受限
  • Kafka 很強大,但太重量級
  • DDS 很可靠,但有 Discovery Storm 問題

Zenoh 出現時,它說:「我可以兼顧所有優點。」更重要的是,它做到了。

而這一切,都建立在 Rust 之上。

選擇 Rust 作為核心語言不是偶然,而是深思熟慮的決定:

  • 記憶體安全:無 GC 的零成本抽象,適合從嵌入式到雲端
  • 並發安全:編譯期保證執行緒安全,避免 data race
  • 零成本抽象:高階語法不犧牲效能,達到 C/C++ 等級的速度
  • 生態系統:Tokio、Serde、PyO3 等工具讓開發更高效

Week 1:認識Zenoh這位新朋友

前七天,我們建立了對 Zenoh 的核心理解:

Zenoh 不只是 pub/sub

這是最常見的誤解。Zenoh 提供了三種核心模式:

  1. Publisher/Subscriber - 資料分發
  2. Get/Queryable - 分散式查詢
  3. Liveliness Tokens - 自動服務發現

這三種模式組合起來,可以實現幾乎所有的分散式通訊場景。

Key Expressions 的威力

// 簡單但強大
"sensor/*/temperature"  // 所有感測器的溫度
"robot/**/status"       // 所有子系統的狀態
"fleet/robot?is_available=true"  // 條件式管理

這種階層式命名空間設計,讓資料組織變得直觀且靈活。

QoS 的藝術

Zenoh 提供了 8 個優先等級,讓我們可以客製化資料的優先度

Priority::RealTime        // 自駕車的剎車指令
Priority::InteractiveHigh // 遙控操作
Priority::DataHigh        // 感測器資料
Priority::Background      // 日誌記錄

配合 Congestion Control(Drop/Block/BlockFirst),你可以精確控制在網路擁塞時該選擇什麼樣的tradeoff。

效能上的突破

當我們在 Day 5 看到 99.97% Discovery 流量減少這個數字時,真的是令人震驚。這不只是漸進式改進,而是解決了困擾 ROS 2 社群多年的根本問題。

  • 傳統 DDS:每個節點廣播 discovery 訊息
  • Zenoh:透過 Router 集中管理以及精心設計的gossip機制

Week 2:深入 Rust 的世界

第二週是技術深度的探討。我們不再只是「使用」Zenoh,而是開始「理解」它。這一週,我們真正看到了 Rust 如何賦能 Zenoh。

微服務架構的實戰

在 Day 8-9,我們構建了完整的微服務系統。這裡有個有趣的發現:

Zenoh + Rust 讓微服務變簡單了

不需要 service registry、load balancer、API gateway。Zenoh 的 Queryable 模式天生就是分散式 RPC,而 Rust 的 async/await 讓非同步程式碼看起來像同步程式碼:

// 服務提供者
session.declare_queryable("service/add")
    .callback(|query| {
        let result = compute(query.value());
        query.reply(result);
    });

// 服務消費者 - 看起來像同步,實際上是非阻塞
let reply = session.get("service/add?x=1&y=2").await;

無需複雜的配置,在 Zenoh 中建立 Service 既直觀又方便,充分展現了Rust 零成本抽象的威力。

Rust 巨集的魔法

Day 10 揭示了 Zenoh 如何用 Rust 的強大巨集系統減少重複程式碼。

好的 API 應該讓正確的事情容易做,錯誤的事情難做。

Zenoh 充分利用 Rust 的巨集能力:

  • #[derive(Parameters)] 自動生成配置邏輯
  • Procedural macros 生成型別安全的 FFI 綁定
  • Trait-based design 統一 sync/async API

這種編譯期程式碼生成(compile-time metaprogramming)讓 Zenoh 能在不犧牲效能的情況下提供優雅的 API。

非同步執行環境的選擇

Day 12 討論了 Zenoh 為什麼選擇 Tokio 而不是 async-std 或 smol。答案很務實:

生態系統 > 純粹效能

雖然 smol 和 async-std 在某些 benchmark 上更快,但 Tokio 有:

  • 更多的第三方函式庫支援
  • 更活躍的社群
  • 更穩定的長期發展

這是一個成熟專案的明智選擇。

Week 3:跨語言的橋樑

第三週最令人印象深刻的是 Zenoh 的跨語言能力。這不只是「能用」,而是「用得好」。Rust 核心的效能和安全性,透過精心設計的 FFI 層延伸到其他語言。

C/C++ 的零成本抽象

Day 14-16 的 Rust-C Bridge 三部曲展示了如何將 Rust 的所有權系統映射到 C,這是一個創新的設計:

記憶體所有權的精確控制

  • z_owned_t - 擁有所有權(對應 Rust 的 owned value)
  • z_loaned_t - 借用參考(對應 Rust 的 &T
  • z_moved_t - 所有權轉移(對應 Rust 的 move semantics)

這種設計讓 C 開發者也能享受 Rust 的記憶體安全保證,即使他們不懂 Rust。編譯器會在編譯期檢查所有權違規,而不是在執行期才發現記憶體錯誤。

現代 C++ API 更進一步:

// RAII + move semantics
auto session = zenoh::Session::open(config);
auto pub = session.declare_publisher("demo/hello");
pub.put("Hello Zenoh!");
// 自動清理,不需要手動 drop

Python 的親和力

Day 17-18 的 Python 綁定解決了一個棘手問題:如何在 GIL 的限制下實現高效能?

答案是 callback-based 的設計搭配 Rust 的 Tokio runtime 在背景執行:

import zenoh

# Rust 的 Tokio runtime 在背景執行
# Python 透過 callback 處理事件
session = zenoh.open(zenoh.Config())

def listener(sample):
    print(f"Received: {sample.payload.decode('utf-8')}")

subscriber = session.declare_subscriber('demo/**', listener)

# 保持執行
input("Press Enter to exit...")

透過 PyO3(Rust 的 Python 綁定框架)的橋接,Python 開發者能用簡潔的語法享受 Zenoh 的效能。重要的是,Rust 的 Tokio runtime 在背景執行,完全不受 GIL 限制。GIL 只在 callback 執行時短暫持有,網路 I/O 和資料處理都在 Rust 側高效執行。

這展示了 Rust 作為「效能基礎設施層」的價值:讓高階語言專注於業務邏輯,底層效能交給 Rust。

Kotlin/JVM 的整合

Day 19 展示了 JNI 的挑戰與解決方案。最有趣的部分是 Arc-based ownership transfer:

Rust 的 Arc 指標可以安全地傳遞給 JVM,讓 garbage collector 和 Rust 的 ownership 系統和平共存。

Week 4:真實世界的衝擊

最後一週,我們探討了一些 Zenoh 的應用,尤其是機器人相關的嶄新想法。

Zenoh Dissector:開發者的 X 光眼

Day 22 的 zenoh-dissector 是一個 Wireshark Plugin。它不只是除錯工具,更是學習 Zenoh 協定的最佳方式。

當我們看到封包在網路中的真實樣貌:

Transport Message
├─ Header (Priority: RealTime)
├─ Body (Type: Data)
│  ├─ Key: robot/odom
│  ├─ Encoding: application/octet-stream
│  └─ Payload: [binary data]
└─ Attachment (optional metadata)

別忘了背後的技術基礎,就是 Rust 強大的 Macro 以及豐富的 Type / Trait 系統, 最後透過 FFI 無縫鏈接既有的 C 函式庫。

ROS 整合:Zenoh 的殺手級應用

Day 24-29 是整個系列的高潮。我們見證了 Zenoh 如何改變機器人開發:

ROS 1 Bridge (Day 24)

  • ALOHA 協調協定避免 discovery 衝突
  • 跨 WAN 的機器人協作成為可能

zenoh-plugin-ros2dds (Day 25)

  • 按需路由,不再浪費頻寬
  • Service 橋接,打通 ROS 2 與 Zenoh 生態

CARLA + Autoware (Day 27)
這是最有趣的展示:在 CARLA 模擬器中管理自駕車車隊,透過 Zenoh 協調多車路徑規劃!

畫面中,多輛自駕車在城市中穿梭,它們的感測器資料、規劃指令、安全警報都透過 Zenoh 無縫流動。

rmw_zenoh (Day 28)

這是 Zenoh 發展史上的里程碑:成為 ROS 2 官方支援的中介層實作

rmw_zenoh 不只是另一個 RMW 實作,它代表了 ROS 2 通訊架構的重大突破:

解決的核心問題

傳統 rmw_fastrtps / rmw_cyclonedds:

  • Discovery Storm:n² 複雜度的 discovery 流量
  • 單網段限制:multicast 無法跨路由器
  • 記憶體佔用:每個節點需維護完整 graph
  • 配置複雜:DDS QoS 設定難以理解

rmw_zenoh 的改進:

  • Discovery 流量減少
  • 原生 WAN/Internet 支援
  • 簡潔的 Zenoh 配置

實際效益

  • 大規模系統:支援數百個節點而不崩潰
  • 分散式機器人:多機器人可跨網段、跨地域協作
  • 雲端整合:邊緣機器人輕鬆連接雲端服務
  • 降低門檻:不需要深入理解 DDS 也能正確配置

官方認可的意義

2024 年,rmw_zenoh 被納入 ROS 2 官方支援清單,這意味著:

  • 長期維護承諾:與 ROS 2 release 同步更新
  • 品質保證:通過完整的 ROS 2 測試套件
  • 生態系統整合:所有 ROS 2 工具無縫支援
  • 社群信心:ROS 社群認可 Zenoh 的技術實力

這確立了 Zenoh 不只是「另一個通訊協定」,而是機器人領域的核心基礎設施

ROS-Z (Day 29)
新的願景:純 Rust 的 ROS 2 堆疊,消除所有中間抽象層。這是終極目標:

傳統 ROS 2 堆疊:
Application (C++/Python)
    ↓
rcl (C)
    ↓
rmw (C)
    ↓
DDS (C++, 多個供應商)

ROS-Z 願景:
Application (Rust)
    ↓
ROS-Z (Pure Rust) / RCL-Z (兼容RCL C API)
    ↓
Zenoh (Pure Rust)

從應用層到網路層,全部使用 Rust。這意味著:

  • 統一的記憶體管理:不再有跨語言邊界的記憶體洩漏
  • 編譯期最佳化:整個堆疊可以一起優化,LLVM 看到完整的程式碼
  • 極致效能:零成本抽象貫穿整個堆疊
  • 更小的二進位檔:不需要多個語言的 runtime

這是 Rust 在系統程式設計領域的願景實現,打造一個 Rust 驅動安全又高效的機器人系統是可能的!

討論:我們學到的不只是技術

1. Rust 不只是實作細節,而是核心優勢

很多專案選擇某個程式語言只是「恰好用了」,但 Zenoh 不同。Rust 是 Zenoh 能達成目標的根本原因:

記憶體安全 = 可靠性

  • 沒有 use-after-free、double-free、data race
  • 在自駕車、醫療機器人等安全關鍵應用中,這是生死攸關的保證
  • 傳統 C/C++ DDS 實作常有記憶體錯誤,Rust 在編譯期就杜絕

零成本抽象 = 效能 + 開發效率

  • 優雅的 API 不犧牲效能
  • Iterator chains、async/await 都會被編譯成最優機器碼

Fearless Concurrency = 可擴展性

  • 多執行緒程式設計不再是雷區
  • 這讓 Zenoh 可以安全地使用所有 CPU 核心

生態系統 = 快速迭代

  • Cargo 讓依賴管理變簡單
  • crates.io 有豐富的函式庫
  • 社群活躍,問題快速解決

如果 Zenoh 用 C++ 寫,可能達到相同效能,但:

  • Runtime bug 會多很多
  • 艱澀難懂的錯誤訊息
  • 跨平台會更困難
  • 新貢獻者門檻會更高

Rust 讓 Zenoh 能同時達到「快、正確、易用」三個目標。這在傳統系統程式設計中是非常少見的,這也是 Rust 的魅力所在!

2. 統一性的力量

Zenoh 用一個協定連接:

  • 微控制器
  • 樹莓派
  • 工業 PC
  • 雲端伺服器
  • Web 瀏覽器

這種垂直整合能力是革命性的。不需要在邊緣用 MQTT,中間用 Kafka,雲端用 gRPC。一個 Zenoh,全部搞定。

這也是 Rust 的貢獻:因為沒有 GC overhead,Rust 可以在資源受限的嵌入式環境執行。因為效能極致,同樣的程式碼可以跑在雲端處理高流量。

3. 效能與易用性不衝突

傳統觀念認為高效能意味著複雜的 API。Zenoh 證明這是錯的:

// 發布資料,就這麼簡單
session.put("sensor/temp", 25.5).await?;

// 訂閱資料,一樣簡單
let subscriber = session.declare_subscriber("sensor/**").await?;

背後可能是 shared-memoary zero-copy、智慧路由、QoS 管理,而開發者完全不需要費任何心思。

這是 Rust 零成本抽象的典範:表達力強的語法(.await?、method chaining)會被優化成效能不輸 C 的機器碼。

4. 開源的商業模式

Zenoh 展示了一個健康的開源商業模式:

  • 核心是 Apache 2.0 開源
  • 社群驅動開發

這確保了 Zenoh 的長期發展,而不會被單一公司綁架。

數字會說話

讓我們用數據總結 Zenoh 的成就:

效能指標
├─ 延遲:5-10µs (P2P, 單機)
├─ 延遲:13-16µs (P2P, 跨機器)
├─ 吞吐量:比 MQTT 高 1-2 個數量級
└─ Discovery 流量:比 DDS 少 99.97%

生態系統
├─ 語言綁定:10+ (Rust, C, C++, Python, Kotlin, TypeScript...)
├─ 傳輸協定:10+ (TCP, QUIC, WebSocket, Serial, Shared Memory...)
├─ 平台支援:從 RTOS 到 Linux/Windows/macOS
└─ Plugin:ROS1/2, DDS, MQTT, WebServer, Storage

如果你是 Rust 開發者

Zenoh 是學習 Rust 進階技巧的絕佳範例專案

想學習的主題 → 參考 Zenoh 的實作

  • Async 程式設計zenoh::Session 的設計
  • Trait 設計ResolvableWaitIntoFuture 模式
  • Macro 編程#[derive(Parameters)] 的實作
  • FFI 設計zenoh-c 的所有權映射
  • Zero-copyZSliceZBuf 的實作
  • 並發控制ZRuntime 的執行緒管理

閱讀 Zenoh 原始碼,你會看到 Rust 的各種最佳實踐:

  • 如何設計 builder pattern
  • 如何用 PhantomData 做型別狀態機
  • 如何用 ArcMutex 做安全的共享狀態
  • 如何設計 plugin 系統
  • 如何實作多種主流語言的 binding

這是真實應用的 Rust,不只是紙上談兵。

社群與資源

加入社群

致謝

這三十天的旅程不可能沒有:

  • Eclipse FoundationZettaScale Technology 的技術創新
  • ROS 社群的合作與採用
  • 所有開源貢獻者的無私付出

結語:旅程才剛開始

三十天前,我們問:「Zenoh 是什麼?」

現在,我們知道它是:

  • 一個高效能的通訊協定
  • 一個跨平台的生態系統
  • 一個連接萬物的願景

但更重要的是,Zenoh 是一個可能性

可能性去建構下一代的機器人系統。
可能性去連接海量的 IoT 設備。
可能性去打造無縫的邊緣到雲端資料流。

而 Rust,是讓這一切成為現實的基石。

Zenoh 展示了 Rust 在系統程式設計領域的潛力:

  • 不只是「更安全的 C++」
  • 而是「讓不可能變可能」的工具

從微控制器到雲端,從單機到分散式,從同步到非同步——Rust 讓開發者能以一致的方式處理所有場景。

你的回饋很重要

這個系列對你有幫助嗎?有什麼可以改進的地方?歡迎在留言區分享你的想法,或是在 GitHub 上開 issue。

如果你開始使用 Zenoh,別忘了回來分享你的經驗。我們都想知道 Zenoh 如何改變了你的專案。

感謝這三十天的陪伴。我們在 Zenoh 社群再見!


上一篇
Day 29: Zenoh 在機器人系統的應用全景 Part 4 - ROS-Z:以原生 Zenoh 釋放 ROS 2 潛力
系列文
30 天玩轉 Zenoh:Rust 助力物聯網、機器人與自駕的高速通訊30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言