Slide 1

Slide 1 text

CEO / CTO ZettaScale Technology Angelo Corsaro, PhD Advanced Zenoh Tutorial

Slide 2

Slide 2 text

https://github.com/kydos/zenoh/tree/dev/zsak Resources We’ll extensively use zenohi an experimental command line tool designed to learn and experiment with Zenoh

Slide 3

Slide 3 text

Get It. Build It. Run It $ git clone [email protected]:kydos/zenoh.git $ git checkout dev/zsak $ cd zenoh $ cargo build —release —features “stats” $ ./target/release/zenohi -h

Slide 4

Slide 4 text

Setting the Context

Slide 5

Slide 5 text

Robotics Body

Slide 6

Slide 6 text

Robotics Body AI Brain

Slide 7

Slide 7 text

Robotics AI Body Brain Nervous System Communication

Slide 8

Slide 8 text

Nervous System Communication

Slide 9

Slide 9 text

The Problem

Slide 10

Slide 10 text

Cloud to Microcontroller Today, more and more systems, operate from the cloud down to the micro-controller This poses new challenges as existing technologies were not designed to work in this scenario Cloud Edge Device

Slide 11

Slide 11 text

A Cross Industry Challenge Robotics Automotive IoT / Edge …

Slide 12

Slide 12 text

Simplicity does not precede complexity, but follows it — A. Perils Digital Frankensteins Today, building systems that span from the micro-controller to the data-centre feels like assembling a digital Frankenstein Multiple technologies are stitched together only to make data fl ow end-to- end Few more have to be packed-up to deal with data storage… Not to mention computations

Slide 13

Slide 13 text

The Solution

Slide 14

Slide 14 text

Core Technology

Slide 15

Slide 15 text

Dragons teach us that if we want to climb high we have to do it against the wind. Pub/Sub/Query protocol that Uni fi es data in motion, data at rest and computations from embedded microcontrollers up the data centre Provides location-transparent abstractions for high performance pub/sub and distributed queries across heterogeneous systems Built-in support for Shared Memory / Zero-Copy as well as built-in support for distributed storage alignments

Slide 16

Slide 16 text

Runs Everywhere Written in Rust for security, safety and performance Native libraries and API bindings for many programming languages, e.g., Rust, C/C++, Python, JS, REST, C# and Kotlin Built-in support Shared Memory and Zero Copy Supports network technologies from transport layer down- to the data link. Currently runs on, TCP/IP, UDP/IP, QUIC, Serial, Bluetooth, OpenThreadX, Unix Sockets, Shared Memory Available on embedded and extremely constrained devices and networks — 5-7 bytes minimal overhead Data Link Network Transport Physical …

Slide 17

Slide 17 text

Why Rust? 70% of security vulnerability are due to memory safety issues Rust is memory and concurrency safe, high performance, productive and has a great ecosystem

Slide 18

Slide 18 text

Zenoh Implementations ZettaScale leads two implementations of the Zenoh protocol Zenoh written in Rust and Zenoh Pico written in C and targeting micro- controllers When using C/C++ APIs, applications can target either of these versions — it is a compile-time decision C C CPP Zenoh Pico Zenoh C Rust CPP Python Kotlin Java TS Rust Go JS

Slide 19

Slide 19 text

Supported OS OS Linux, MacOS, Windows, Android, iOS, QNX Embedded Targets Arduino, ESP32, Zephyr, FreeRTOS, … Automotive Targets AUTOSAR Classic (microSAR)

Slide 20

Slide 20 text

Any Topology Peer-to-peer Clique and mesh topologies Mesh Peer Peer Peer Peer Peer Clique Peer Peer Peer Peer

Slide 21

Slide 21 text

Any Topology Peer-to-peer Clique and mesh topologies Client Client Mesh Peer Peer Peer Peer Peer Clique Peer Peer Peer Peer Client

Slide 22

Slide 22 text

Any Topology Peer-to-peer Clique and mesh topologies Brokered Routed Client Client Brokered Clients communicate through a router or a peer Mesh Peer Peer Peer Peer Peer Router Client Client Client Client Router Router Client Clique Peer Peer Peer Peer Client

Slide 23

Slide 23 text

Router Router Any Topology Peer-to-peer Clique and mesh topologies Brokered Routed Router Router Router Client Client Routed Routers forward data to and from peers and clients Brokered Clients communicate through a router or a peer Mesh Peer Peer Peer Peer Peer Router Client Client Client Client Router Router Client Clique Peer Peer Peer Peer Client

Slide 24

Slide 24 text

Putting it all Together Each Zenoh application can transparently run across multiple links at the same time All of this transparently to the application Router Router Router Client Client Client Peer Peer Peer Peer Peer serial Unix Pipes OpenThread Serial TCP/IP QUIC QUIC QUIC TLS TLS TLS Unix Sockets

Slide 25

Slide 25 text

Topology in Perspective

Slide 26

Slide 26 text

Zenoh Runtime Storage Plugins Protocol Plugins MAIN MEMORY FILE SYSTEM Runtime Plugins Zenoh Flow RocksDB Plug-In Architecture

Slide 27

Slide 27 text

Programming Abstractions

Slide 28

Slide 28 text

Zenoh’s Primitives Zenoh is built upon two primitives operating on named data: pub/sub and query/reply Named data is represented by as (key, value) tuple, e.g., (bot-1/sensor/speed, 25) These two orthogonal primitives allow Zenoh to e ffi ciently deal with distributed computations, data/event dissemination and storage

Slide 29

Slide 29 text

bot-1/sensor/speed Pub/Sub Cont Pub Sub1 Sub2 Sub3 bot-1/sensor/* bot-1/sensor/speed bot-2/sensor/speed Sub4 Sub5 bot-2/** bot-2/sensor/speed Pub */sensor/* Zenoh matching is based on key expressions A subscriber has associated a key expression and will receive all publications with a matching key

Slide 30

Slide 30 text

Composing Zenoh’s Abstractions Publish/Subscribe. Trivially supported by Zenoh’s Publisher and Subscriber Remote Computation. A Queryable represents a generalised computation, since it can transparently deal with replication and partitioning Storage. Represented by the combination of a Queryable and a Subscriber Additionally all these primitives enjoy location transparency by the virtue of being data-centric. Recap

Slide 31

Slide 31 text

Sub1 Queryable1 Sub1 Queryable1 Example — Storage The combination of a Subscriber and a Queryable allow to abstract any storage Each publication matching the Subscriber expression will be ingested on the storage Every query matching the Queryable will result on a storage query Zenoh provides o ff the shelf integration with mainstream storage technologies Sub1 Queryable1 In fl uxDB File System AWS S3 bot$*/sensor/** bot$*/sensor/** bot$*/sensor/**

Slide 32

Slide 32 text

bot-1/compute/nav/path Query/Reply When issuing a query Zenoh will route it to a set of Queryable The set of queryable addressed depends on the query target, it can be Best Matching, All and All Complete Triggered queryable respond with a fi nite stream of values Get Queryable1 bot-1/compute/nav/* Queryable2 bot-*/compute/nav/* Queryable3 bot-1/compute/nav/path

Slide 33

Slide 33 text

bot-1/compute/nav/path Query/Reply Cont Get Queryable1 bot-1/compute/nav/* Queryable2 bot-*/compute/nav/* Queryable3 bot-1/compute/nav/path ALL When issuing a query Zenoh will route it to a set of Queryable The set of queryable addressed depends on the query target, it can be Best Matching, All and All Complete Triggered queryable respond with a fi nite stream of values

Slide 34

Slide 34 text

Query/Reply Cont When issuing a query Zenoh will route it to a set of Queryable The set of queryable addressed depends on the query target, it can be Best Matching, All and All Complete Queryable1 Queryable3 BEST MATCH Assuming Queryable3 is the closest in routing distance bot-1/compute/nav/path bot-1/compute/nav/* bot-*/compute/nav/* bot-1/compute/nav/path Get Queryable2

Slide 35

Slide 35 text

Query/Reply Cont When issuing a query Zenoh will route it to a set of Queryable The set of queryable addressed depends on the query target, it can be Best Matching, All and All Complete Get Queryable1 Queryable2 Queryable3 ALL COMPLETE Completeness allows to indicate that a queryable does not have “holes”. In other terms it commits to provide answers for any key included in its key expression bot-1/compute/nav/path bot-1/compute/nav/* bot-*/compute/nav/* bot-1/compute/nav/path

Slide 36

Slide 36 text

Example Let’s assume that each robot exposes a queryable to retrieve status Notice that when we do a query we don’t need to know if the data is being computed or retrieved from a store Zenoh abstracts the di ff erence between the two — which is extremely fl exible Get Queryable1 Queryable2 Queryable3 bot-1/status/** bot-2/status/** bot-2/status/**

Slide 37

Slide 37 text

Example Let assume we want to get the battery status for bot1 get bot-1/status/battery Get Queryable1 Queryable2 Queryable3 84%, nil bot-1/status/** bot-2/status/** bot-2/status/** 84% 42% 21%

Slide 38

Slide 38 text

84%, nil 42%, nil 21%, nil Example Let assume we want to get the battery status for all bots get bot-$*/status/battery Get Queryable1 Queryable2 Queryable3 bot-1/status/** bot-2/status/** bot-2/status/** 84% 42% 21%

Slide 39

Slide 39 text

nil 42%, nil 21%, nil Example Let assume we want to get the battery status for all bots that have less than 50% of remaining charge get bot-$*/status/battery?level<0.5 Get Queryable1 Queryable2 Queryable3 bot-1/status/** bot-2/status/** bot-2/status/** 84% 42% 21%

Slide 40

Slide 40 text

Rust API

Slide 41

Slide 41 text

API Design Support for both async and sync programming model Builders everywhere to ensure evolvability Needs to “resolve” by calling res() in order to craft the request

Slide 42

Slide 42 text

Synch or Async: Pick Your Choice Zenoh supports both sync and async APIs Depending on your application and the integration requirement with other libraries and native code it may be preferable to use one or the other To use the sync API you need to use the zenoh.Wait trait.

Slide 43

Slide 43 text

Opening a Session #[tokio::main] async fn main() { let c = zenoh::Config::default(); let z = zenoh::open(c).await.unwrap(); // Use the session } Sync API Async API use zenoh::Wait; fn main() { let c = zenoh::Config::default(); let z = zenoh::open(c).wait().unwrap(); // Use the session }

Slide 44

Slide 44 text

Publishing Data

Slide 45

Slide 45 text

Producing Data w/o a Publisher Zenoh makes it possible to “put” data without needing to declare a publisher The declaration of a publisher is just an optimisation that should be done for resources that are written regularly z.put("daily/quote/latin", "Per aspera ad astra.").await.unwrap(); z.put("daily/quote/hindi", "A união faz a força.").await.unwrap();

Slide 46

Slide 46 text

Producing Data with a Publisher The declaration of a publisher is just an optimisation It is a way to indicating to Zenoh that a given resource is going to be written often and thus implement a series of runtime and wire optimisations — in other terms make the common case fast! let z_pub = z.declare_publisher("daily/quote/latin").await.unwrap(); z_pub.put("Audaces fortuna juvat.").await.unwrap(); Publishers can be declared for any valid key expression, such as, daily/quote/latin , daily/quote/*, daily/quote/**

Slide 47

Slide 47 text

What can I “put”? pub fn put(&self, payload: IntoZBytes) -> PublisherPutBuilder<'_> where IntoZBytes: Into, In Zenoh you can put anything that can be converted into ZBytes This includes, strings, vectors, slices and arrays of u8, and Shared Memory bu ff ers

Slide 48

Slide 48 text

Subscribing

Slide 49

Slide 49 text

Subscriber Declaration A subscriber is declared by providing a key expression, such as, daily/quote/* and daily/** Zenoh guarantees that a subscriber will receive the put operation performed for keys- expressions that match with that of the subscriber Example: A Subscriber for daily/quote/* matches daily/quote/latin and daily/quote/ brazilian, while daily/** matches daily/quote/latin daily/quote/brazilian daily/world/english, etc. let sub = z.declare_subscriber("daily/quote/*").await.unwrap();

Slide 50

Slide 50 text

Samples received by a subscriber can be consumed asynchronously using a stream and as such avoiding any inversion of control This keeps the code highly readable and can leverage all the stream combinators Subscribers as Streams let sub = z.declare_subscriber("daily/quote/**").await.unwrap(); while let Ok(s) = sub.recv_async().await { println!("{}: {}", s.key_expr(), s.payload().try_to_string().unwrap()); } let kvs = sub.iter().fuse() .map(|s| { let k = String::from(s.key_expr().as_str()); let v = String::from(s.payload().try_to_string().unwrap()); (k, v)});

Slide 51

Slide 51 text

Query

Slide 52

Slide 52 text

Queryable A queryable is a network endpoint that answers to queries matching its key expression The answer to a query is a fi nite stream of (key, values) Queryable are quite powerful and can be used to represent both the reading-half of a datastore/database as well as trigger computations

Slide 53

Slide 53 text

Declaring a Queryable The declaration of a queryable requires minimally the key expression associated with it let queryable = z.declare_queryable("daily/quote/**") .complete(is_complete) .await.unwrap(); You can also specify the completeness of this queryable w.r.t. the set of keys represented by its key expression. If the queryable “has answers” for any key in the set expressed by its key expression then it ice complete, otherwise it is not.

Slide 54

Slide 54 text

Visualizing Completeness Another way of visualising complete queryable, is like a set w/o any “holes” This property is especially important if you want to use queryable to do quorums Complete Non Complete

Slide 55

Slide 55 text

Query In Zenoh queries are issued by using the get operation z.get(k) .target(query_target) .consolidation(consolidation) .res().await.unwrap(); The result of a query is a fi nite stream of Replies Controls who, among matching, is eligible to be targeted Controls if and how replies are consolidated

Slide 56

Slide 56 text

Query Target The query target controls, among the queryable whose key expression matches that of the query, the set that should be used to execute the query pub enum QueryTarget { #[default] BestMatching, All, AllComplete, #[cfg(feature = "complete_n")] Complete(u64), } BestMatching. Bigger intersection and closer in routing terms All. All the queryable that intersect the query AllComplete. All queryable that fully cover the query. In other terms the query key expression is superset of the query expression Complete(N). Among the queryable that are complete pick N — routing considerations will be used to decide. (This is useful for read quorums, N is your read quorum :-)

Slide 57

Slide 57 text

Key Highlights Zenoh is one of a kind protocol — it uni fi es data in motion, data at rest and computations It is the only protocol able to run from the microcontroller up to the datacenter It has not topological constraints It is extremely easy to use!

Slide 58

Slide 58 text

Patience, persistence and perspiration make an unbeatable combination for success. Thank You