gRPC-Rust

repository·master·Indexed 11 days ago

https://github.com/grpc/grpc-rust

A preview implementation of gRPC for Rust. The project includes the core grpc crate, the protoc-gen-rust-grpc code generator, grpc-protobuf-build for build integration, and grpc-protobuf for protobuf-over-grpc implementation. It also features Tonic, a high-performance gRPC implementation built on tokio and hyper with async/await support. Minimum Supported Rust Version (MSRV) is 1.88.

Tokens
46.8K
Snippets
145
Records
205
Agent score
94%

What's inside gRPC-Rust

  1. Overview of Tonic gRPC implementation

    master

    Tonic is a high-performance gRPC over HTTP/2 implementation for Rust. It is designed with first-class support for async/await and is built to serve as a core building block for production systems.

    Key features include:

    • Bi-directional streaming
    • High performance async I/O
    • Interoperability
    • TLS support via rustls
    • Load balancing
    • Custom metadata
    • Authentication
    • Health Checking
  2. Overview of the gRPC Benchmarking Framework

    master

    The grpc-benchmark package provides the core implementations for the gRPC benchmarking framework. It includes the worker, server, and client implementations required to perform performance testing.

    Note that this package contains the implementation logic, but the driver code and the instructions to execute benchmarks are located in the main grpc/grpc repository under tools/run_tests/performance/.

  3. Use `grpc-protobuf` for Protobuf integration

    master

    The grpc-protobuf crate provides the necessary types for applications to perform and control RPCs within the grpc ecosystem.

    Important Note: This crate is currently in a preview state. All APIs are unstable and not recommended for production use. Proceed at your own risk.

    Most types used with this crate are generated by the protoc-gen-rust-grpc plugin from your .proto files.

  4. Use tonic-health for gRPC healthchecks

    master

    tonic-health is a gRPC healthcheck implementation built on top of tonic. It follows the official gRPC health checking protocol, allowing clients to query the status of services.

    To implement or use healthchecks, refer to the official tonic examples for the full integration pattern.

  5. Implement the gRPC Richer Error Model with `tonic-types`

    master

    The tonic-types crate provides protobuf types and the StatusExt trait to implement the gRPC Richer Error Model in tonic.

    It allows servers to attach structured error details (like BadRequest violations or help links) to a tonic::Status, and allows clients to easily extract these details.

    Key components:

    • pb module: Contains useful protobuf types.
    • ErrorDetails struct: A builder-like struct for aggregating multiple error details.
    • StatusExt trait: Implemented for tonic::Status, providing methods to create statuses with details on the server and extract details on the client.
  6. Use tonic-reflection for gRPC reflection

    master
    The tonic-reflection crate provides a gRPC reflection implementation built on top of tonic. It allows gRPC clients (such as grpcurl or Postman) to query a server for information about its services, methods, and message types, enabling dynamic interaction without pre-compiled stubs.
  7. Define gRPC service methods in Protocol Buffers

    master

    gRPC services are defined in .proto files. Tonic supports the four standard gRPC communication patterns by using the stream keyword in the service definition:

    1. Simple RPC: A single request and a single response. rpc Method(Request) returns (Response) {}
    2. Server-side streaming RPC: The client sends one request and receives a stream of messages. rpc Method(Request) returns (stream Response) {}
    3. Client-side streaming RPC: The client sends a stream of messages and receives one response. rpc Method(stream Request) returns (Response) {}
    4. Bidirectional streaming RPC: Both client and server send streams of messages independently. rpc Method(stream Request) returns (stream Response) {}
    // Example of a bidirectional streaming RPC
    service RouteGuide {
       rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
    }
    
    // Example of a message definition
    message Point {
      int32 latitude = 1;
      int32 longitude = 2;
    }
  8. How Tonic is architected

    master

    Tonic is composed of three primary architectural components:

    1. Generic gRPC implementation: A core implementation that can support any HTTP/2 implementation and any encoding through a set of generic traits.
    2. HTTP/2 implementation: Based on hyper, a fast HTTP/1.1 and HTTP/2 client and server built on the tokio stack.
    3. Codegen: Tools powered by prost used to build clients and servers from Protocol Buffers (protobuf) definitions.
  9. Understand Tonic benchmark scope and limitations

    master

    When analyzing the results of the Tonic benchmarks, keep the following constraints in mind:

    • Scope: These benchmarks measure the performance of constructing Tonic Requests and Responses. They do not measure over-the-wire network throughput.
    • Throughput (thrpt): The throughput value reported by Criterion is a measure of the bytes consumed by the target function, not network speed.
    • Compilation: The benchmarks use pre-compiled .rs files located in benchmarks/compiled_protos to avoid measuring tonic-build compilation time. The original .proto files are available in the proto directory for reference.
  10. Handle different gRPC RPC patterns

    master

    Tonic supports four types of RPC patterns. All service methods receive a tonic::Request<T> and return a Result<tonic::Response<T>, tonic::Status>. The type of T depends on your .proto definition:

    1. Simple RPC: Receives a single value and returns a single value.
    2. Server-side streaming RPC: Receives a single value and returns a Stream of values. You can use tokio::sync::mpsc and tokio_stream::wrappers::ReceiverStream to implement this.
    3. Client-side streaming RPC: Receives a tonic::Streaming<T> and returns a single value. You can iterate over the stream using StreamExt::next().
    4. Bidirectional streaming RPC: Receives a tonic::Streaming<T> and returns a Stream of values. The async_stream crate is useful for yielding values from an asynchronous transformation.
    // Simple RPC
    async fn get_feature(&self, request: Request<Point>) -> Result<Response<Feature>, Status> {
        Ok(Response::new(feature))
    }
    
    // Server-side streaming
    type ListFeaturesStream = ReceiverStream<Result<Feature, Status>>;
    async fn list_features(&self, request: Request<Rectangle>) -> Result<Response<Self::ListFeaturesStream>, Status> {
        let (tx, rx) = mpsc::channel(4);
        // ... spawn task to send items to tx
        Ok(Response::new(ReceiverStream::new(rx)))
    }
    
    // Client-side streaming
    async fn record_route(&self, request: Request<tonic::Streaming<Point>>) -> Result<Response<RouteSummary>, Status> {
        let mut stream = request.into_inner();
        while let Some(point) = stream.next().await {
            let point = point?;
            // ... process point
        }
        Ok(Response::new(summary))
    }
    
    // Bidirectional streaming
    type RouteChatStream = Pin<Box<dyn Stream<Item = Result<RouteNote, Status>> + Send + 'static>>;
    async fn route_chat(&self, request: Request<tonic::Streaming<RouteNote>>) -> Result<Response<Self::RouteChatStream>, Status> {
        let mut stream = request.into_inner();
        let output = async_stream::try_stream! {
            while let Some(note) = stream.next().await {
                let note = note?;
                yield note;
            }
        };
        Ok(Response::new(Box::pin(output) as Self::RouteChatStream))
    }
  11. Understand the gRPC-Rust project layout

    master

    The repository is organized into several key crates that provide different parts of the gRPC ecosystem:

    • grpc: The core gRPC implementation crate.
    • protoc-gen-rust-grpc: The protobuf code generator binary, designed to be used with protoc.
    • grpc-protobuf-build: Provides build integration for generating protobuf code within a Rust build process.
    • grpc-protobuf: The implementation of protobuf-over-grpc used by the code generated by the plugin.
  12. Use alternative error detail extraction methods

    master

    For more granular control or specific use cases, StatusExt provides alternative ways to interact with error details:

    • Vector-based approach: Use StatusExt::with_error_details_vec (server) and StatusExt::get_error_details_vec (client) to work with a Vec<ErrorDetail> (where ErrorDetail is an enum). This provides more control over the exact sequence of standard error messages.
    • Direct extraction: If you only care about one specific error type, use direct methods like StatusExt::get_details_bad_request to extract a BadRequest message directly from a tonic::Status without parsing the entire ErrorDetails struct.