Skip to content

Latest commit

 

History

History
112 lines (89 loc) · 2.13 KB

protobuf-grpc.md

File metadata and controls

112 lines (89 loc) · 2.13 KB

Protobuf and gRPC in Rust

Prost

Prost is a crate implementing protobuf encode/decoding.

cargo add prost
cargo add prost-types   // if you need to use common protobuf types such as Struct, Timestamp, ...

Create a Prost timestamp

let now = chrono::offset::Utc::now();
let timestamp = prost_types::Timestamp {
  seconds: now.timestamp(),
  nanos: now.timestamp_subsec_nanos() as i32,
};

Build protobuf spec with Prost

TBD

Tonic

Tonic is a crate implementing the gRPC protocol on top of HTTP/2 and Prost.

Build a gRPC server with Tonic

File hierarchy used for this section.

proto/
  metrics/
    v1/
      metrics_service.proto
  ...
src/
  lib.rs
Cargo.toml
build.rs

Add the following dependencies in Cargo.toml.

[dependencies]
tonic = "0.5"
prost = "0.8"

[build-dependencies]
tonic-build = "0.5"

Add the following build.rs file at the root level.

fn main() -> Result<(), Box<dyn std::error::Error>> {
    tonic_build::configure().compile(
        &[
            "proto/metrics/v1/metrics_service.proto",
            ...
        ],
        &["proto"],
    )?;

    Ok(())
}

Declare the modules generated by Tonic in lib.rs

pub mod metrics {
    pub mod proto {
        pub mod v1 {
            tonic::include_proto!("metrics.v1");
        }
    }
    
    ...
}

Multiple instances of a gRPC service listening to the same port

Based on SO_REUSEPORT.

let service = YourGrpcService::default();

let addr: std::net::SocketAddr = "0.0.0.0:<port>".parse().unwrap();
let sock = socket2::Socket::new(
  match addr {
    SocketAddr::V4(_) => socket2::Domain::IPV4,
    SocketAddr::V6(_) => socket2::Domain::IPV6,
  },
  socket2::Type::STREAM,
  None,
).unwrap();

sock.set_reuse_address(true).unwrap();
sock.set_reuse_port(true).unwrap();
sock.set_nonblocking(true).unwrap();
sock.bind(&addr.into()).unwrap();
sock.listen(8192).unwrap();

let incoming = tokio_stream::wrappers::TcpListenerStream::new(TcpListener::from_std(sock.into()).unwrap());

Server::builder()
  .add_service(YourGrpcService::new(service))
  .serve_with_incoming(incoming)
  .await
  .unwrap();