還記得第一次接觸 Zenoh 時的疑惑嗎?「又一個訂閱發佈的通訊協定?它跟 MQTT、DDS、Kafka 有什麼不同?」三十天過去了,我們不僅找到了答案,更發現了一個連接萬物的全新視角。
讓我們回顧這段精彩的探索之旅。
在第一週,我們提出了一個關鍵問題:為什麼機器人和 IoT 領域需要 Zenoh?
答案逐漸清晰:
Zenoh 出現時,它說:「我可以兼顧所有優點。」更重要的是,它做到了。
而這一切,都建立在 Rust 之上。
選擇 Rust 作為核心語言不是偶然,而是深思熟慮的決定:
前七天,我們建立了對 Zenoh 的核心理解:
Zenoh 不只是 pub/sub
這是最常見的誤解。Zenoh 提供了三種核心模式:
這三種模式組合起來,可以實現幾乎所有的分散式通訊場景。
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 社群多年的根本問題。
第二週是技術深度的探討。我們不再只是「使用」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 零成本抽象的威力。
Day 10 揭示了 Zenoh 如何用 Rust 的強大巨集系統減少重複程式碼。
好的 API 應該讓正確的事情容易做,錯誤的事情難做。
Zenoh 充分利用 Rust 的巨集能力:
#[derive(Parameters)]
自動生成配置邏輯這種編譯期程式碼生成(compile-time metaprogramming)讓 Zenoh 能在不犧牲效能的情況下提供優雅的 API。
Day 12 討論了 Zenoh 為什麼選擇 Tokio 而不是 async-std 或 smol。答案很務實:
生態系統 > 純粹效能
雖然 smol 和 async-std 在某些 benchmark 上更快,但 Tokio 有:
這是一個成熟專案的明智選擇。
第三週最令人印象深刻的是 Zenoh 的跨語言能力。這不只是「能用」,而是「用得好」。Rust 核心的效能和安全性,透過精心設計的 FFI 層延伸到其他語言。
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
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。
Day 19 展示了 JNI 的挑戰與解決方案。最有趣的部分是 Arc-based ownership transfer:
Rust 的 Arc
指標可以安全地傳遞給 JVM,讓 garbage collector 和 Rust 的 ownership 系統和平共存。
最後一週,我們探討了一些 Zenoh 的應用,尤其是機器人相關的嶄新想法。
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 函式庫。
Day 24-29 是整個系列的高潮。我們見證了 Zenoh 如何改變機器人開發:
CARLA + Autoware (Day 27)
這是最有趣的展示:在 CARLA 模擬器中管理自駕車車隊,透過 Zenoh 協調多車路徑規劃!
畫面中,多輛自駕車在城市中穿梭,它們的感測器資料、規劃指令、安全警報都透過 Zenoh 無縫流動。
這是 Zenoh 發展史上的里程碑:成為 ROS 2 官方支援的中介層實作。
rmw_zenoh 不只是另一個 RMW 實作,它代表了 ROS 2 通訊架構的重大突破:
解決的核心問題
傳統 rmw_fastrtps / rmw_cyclonedds:
rmw_zenoh 的改進:
實際效益
官方認可的意義
2024 年,rmw_zenoh 被納入 ROS 2 官方支援清單,這意味著:
這確立了 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。這意味著:
這是 Rust 在系統程式設計領域的願景實現,打造一個 Rust 驅動安全又高效的機器人系統是可能的!
很多專案選擇某個程式語言只是「恰好用了」,但 Zenoh 不同。Rust 是 Zenoh 能達成目標的根本原因:
記憶體安全 = 可靠性
零成本抽象 = 效能 + 開發效率
Fearless Concurrency = 可擴展性
生態系統 = 快速迭代
如果 Zenoh 用 C++ 寫,可能達到相同效能,但:
Rust 讓 Zenoh 能同時達到「快、正確、易用」三個目標。這在傳統系統程式設計中是非常少見的,這也是 Rust 的魅力所在!
Zenoh 用一個協定連接:
這種垂直整合能力是革命性的。不需要在邊緣用 MQTT,中間用 Kafka,雲端用 gRPC。一個 Zenoh,全部搞定。
這也是 Rust 的貢獻:因為沒有 GC overhead,Rust 可以在資源受限的嵌入式環境執行。因為效能極致,同樣的程式碼可以跑在雲端處理高流量。
傳統觀念認為高效能意味著複雜的 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 的機器碼。
Zenoh 展示了一個健康的開源商業模式:
這確保了 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
Zenoh 是學習 Rust 進階技巧的絕佳範例專案:
想學習的主題 → 參考 Zenoh 的實作
zenoh::Session
的設計Resolvable
、Wait
、IntoFuture
模式#[derive(Parameters)]
的實作zenoh-c
的所有權映射ZSlice
和 ZBuf
的實作ZRuntime
的執行緒管理閱讀 Zenoh 原始碼,你會看到 Rust 的各種最佳實踐:
PhantomData
做型別狀態機Arc
和 Mutex
做安全的共享狀態這是真實應用的 Rust,不只是紙上談兵。
這三十天的旅程不可能沒有:
三十天前,我們問:「Zenoh 是什麼?」
現在,我們知道它是:
但更重要的是,Zenoh 是一個可能性。
可能性去建構下一代的機器人系統。
可能性去連接海量的 IoT 設備。
可能性去打造無縫的邊緣到雲端資料流。
而 Rust,是讓這一切成為現實的基石。
Zenoh 展示了 Rust 在系統程式設計領域的潛力:
從微控制器到雲端,從單機到分散式,從同步到非同步——Rust 讓開發者能以一致的方式處理所有場景。
這個系列對你有幫助嗎?有什麼可以改進的地方?歡迎在留言區分享你的想法,或是在 GitHub 上開 issue。
如果你開始使用 Zenoh,別忘了回來分享你的經驗。我們都想知道 Zenoh 如何改變了你的專案。
感謝這三十天的陪伴。我們在 Zenoh 社群再見!