Volo RPC Framework

repository·main·Indexed 25 days ago

https://github.com/cloudwego/volo

A high-performance, extensible Rust RPC framework supporting Thrift, gRPC, and HTTP protocols. It includes volo-cli for project bootstrapping and IDL management, volo-build for compiling Thrift and Protobuf IDLs into Rust code, and a flexible middleware abstraction layer using the #[service] macro. Key features include multi-service support in volo-thrift with ISN routing and a high-performance middleware abstraction called Motore.

Tokens
24.8K
Snippets
31
Records
186
Agent score
82%

What's inside Volo

  1. Overview of volo-grpc

    main

    volo-grpc is a Protobuf-based RPC framework.

    Note for Users: Most developers do not interact with volo-grpc directly. Instead, you should use the Client and Server types provided within the code generated from your Protobuf definitions.

    Note for Extension Developers: If you are building plugins or extending the framework, you may need to interface with the internal components of volo-grpc.

  2. Overview of Volo RPC Framework

    main

    Volo is a high-performance, extensible Rust RPC framework developed by the ByteDance service framework team. It leverages modern Rust features like AFIT (Async Function in Traits) and RPITIT (Return Position Impl Trait in Trait) to provide a high-performance middleware abstraction layer called Motore.

    Key features include:

    • High Performance: Designed to minimize overhead using Rust's static dispatch and compilation optimizations.
    • Ease of Use: Provides the volo-cli for project scaffolding and IDL management, and the #[service] macro to simplify writing asynchronous middleware without manual Box allocations.
    • Extensibility: Uses a flexible middleware Service abstraction, allowing developers to implement service discovery, load balancing, and other governance features as standard Services.
  3. Overview of volo-thrift

    main

    volo-thrift is a Thrift-based RPC framework implementation within the Volo ecosystem.

    Usage Note: Most application developers should not interact with volo-thrift directly. Instead, you should use the Client and Server types provided by the code generated from your Thrift definitions. volo-thrift is primarily intended for extension developers who need to build components that integrate with the Thrift RPC layer.

  4. Use volo-build to compile IDL files

    main

    If you are not using volo-cli, you can use volo-build to compile Thrift and Protobuf IDL files into Rust code at compile-time. This requires adding volo-build as a build dependency, configuring a build.rs file, and defining your IDLs in a volo.yml file.

    1. Add dependency

    Add volo-build to your Cargo.toml under [build-dependencies]. Ensure the version is compatible with your volo version.

    2. Configure build.rs

    Create a build.rs file in your project root with the following content:

    3. Configure volo.yml

    Create a volo.yml file in the same directory as build.rs to specify the source of your IDLs (local files, specific paths in a proto directory, or remote git repositories).

    [build-dependencies]
    volo-build = "*" # make sure you use a compatible version with `volo`
    fn main() {
        volo_build::Builder::default().write().unwrap();
    }
    ---
    idls:
      - source: local
        path: path/to/your/idl.thrift
      - source: local
        path: path/to/your/protobuf/idl.proto
        includes:
        - path/to/your/protobuf/
      - source: git
        repo: git@github.com:cloudwego/volo.git
        ref: main
        path: path/in/repo/idl.thrift
  5. Use volo-cli subcommands

    main

    The volo CLI provides several subcommands to manage your Volo project lifecycle:

    • init: Initialize a new project with a default layout.
    • idl: Manage your Interface Definition Languages (IDLs).
    • repo: Manage your repository.
    • migrate: Automatically migrate from a previous configuration to the latest one.
    • help: Print help information for the CLI or specific subcommands.
  6. Implement Multi-Service support in Volo-Thrift

    main

    Volo-Thrift's Multi Service feature allows a single volo-thrift Server to handle multiple Thrift Services simultaneously. Routing is performed using the isn (IDL Service Name) field within the TTHeader.

    Key Features:

    • Multi-service support: Register multiple Thrift services on one server.
    • ISN Routing: Automatic routing based on the isn field in request headers.
    • Default Service: Configure a fallback service for requests with no isn or an unknown isn.
    • Zero-copy: Uses Bytes for request/response passing to avoid redundant serialization.
    • Backward Compatibility: The single-service API remains unchanged.
  7. Create a Multi-Service Server with Router

    main

    To host multiple services, you must implement the service handlers, wrap them using from_handler, and register them with a Router.

    1. Implement Handlers: Implement the generated trait for each service. Ensure your implementation derives Clone.
    2. Wrap Services: Use *ServiceServer::from_handler(handler) to create service instances.
    3. Configure Router: Use Router::new() to build the routing table.
    4. Start Server: Use Server::with_router(router) to run the server.
    use volo_thrift::server::{Router, Server};
    use std::net::SocketAddr;
    
    #[volo::main]
    async fn main() {
        let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
    
        // 1. Create service instances using from_handler
        let hello_service = volo_gen::hello::HelloServiceServer::from_handler(HelloServiceImpl);
        let echo_service = volo_gen::echo::EchoServiceServer::from_handler(EchoServiceImpl);
    
        // 2. Create Router and register services
        let router = Router::new()
            .with_default_service(hello_service)  // Sets the fallback service
            .add_service(echo_service);           // Adds an additional service
    
        // 3. Start the Server with the router
        Server::with_router(router)
            .run(volo::net::Address::from(addr))
            .await
            .unwrap();
    }
  8. Use the Router to define HTTP routes

    main

    The Router is used to map URI paths to specific handlers or services. It supports normal paths, named parameters, and catch-all parameters.

    Path Patterns

    • Normal Path: /path matches exactly.
    • Named Parameters: /{id} matches segments until the next / or end of path. Parameters can be extracted using PathParamsMap or PathParams<T>.
    • Catch-all Parameters: /{*fallback} matches everything from that point to the end of the path. These must be placed at the end of the route.

    Basic Usage

    use volo_http::server::route::{Router, get};
    
    async fn index() -> &'static str {
        "Hello, World"
    }
    
    let router: Router = Router::new().route("/", get(index));