#rpc #service #helper #generate #prost-build #rpc-server #prost-simple-rpc

prost-simple-rpc-build

为 prost-simple-rpc 提供构建脚本辅助工具

5 个不稳定版本

使用旧的 Rust 2015

0.3.0 2018 年 8 月 7 日
0.2.1 2018 年 4 月 2 日
0.2.0 2018 年 4 月 2 日
0.1.2 2018 年 4 月 1 日
0.1.1 2018 年 3 月 31 日

#219WebSocket

MIT 许可证

15KB
301

prost-simple-rpc

你是否想使用类型安全的基于 Protobuf 的 RPC,而无需使用像 gRPC 这样重量级的工具?

这个库允许你使用 Protobuf 作为模式语言生成用于实现通用 RPC 机制的 trait。你必须提供自己的底层传输机制,例如 WebSockets、UNIX 管道、HTTP 等。

待办事项

这个库相当完整,但在发布 "1.0" 版本之前,还有一些事情我想修复。

  • 清理代码生成代码。
  • 在生成的客户端代码中使用未装箱的未来。
  • 在生成的服务器代码中使用未装箱的未来。
  • 尝试支持不实现 failure::Fail 的执行错误。

用法

有关完整示例,请参阅 示例目录

首先,在例如 src/schema/echo/service.proto 中定义你的服务的模式。

syntax = "proto3";

package echo;

// The Echo service. This service returns back the same data that it is given.
service Echo {
  // Echoes back the data sent, unmodified.
  rpc Echo (EchoRequest) returns (EchoResponse);
}

// The request for an `Echo.Echo` call.
message EchoRequest {
  // The data to be echoed back.
  bytes data = 1;
}

// The response for an `Echo.Echo` call.
message EchoResponse {
  // The echoed back data from `EchoRequest.data`.
  bytes data = 1;
}

使用 prostprost-buildprost-simple-rpc-build 在你的 build.rs 中为该服务生成 Rust 代码。

extern crate prost_build;
extern crate prost_simple_rpc_build;

fn main() {
    prost_build::Config::new()
        .service_generator(Box::new(prost_simple_rpc_build::ServiceGenerator::new()))
        .compile_protos(
            &["src/schema/echo/service.proto"],
            &["src/schema"],
        )
        .unwrap();
}

然后,将生成的代码包含到你的 Rust 构建中,例如在 main.rs 中。生成的代码有一些额外的 crate 依赖项

extern crate bytes;
extern crate failure;
extern crate futures;
extern crate prost;
#[macro_use]
extern crate prost_derive;
extern crate prost_simple_rpc;
extern crate tokio;

mod schema {
    pub mod echo {
        include!(concat!(env!("OUT_DIR"), "/echo.rs"));
    }
}

fn main() {
    // ...
}

客户端

假设你想为你的服务创建一个客户端。你需要实现一个 Handler 来处理客户端调用的传输。让我们假设你有一些形式的 WebSockets 传输

struct WebSocketTransport { /* ... */ }

impl prost_simple_rpc::handler::Handler for WebSocketTransport {
    // From our imaginary websocket library:
    type Error = websocket::Error;
    // This type is generated by prost-simple-rpc:
    type Descriptor = schema::echo::EchoDescriptor;
    // From our imaginary websocket library:
    type CallFuture = websocket::Future;

    /// Perform a raw call to the specified service and method.
    fn call(
        &mut self,
        method: <Self::Descriptor as descriptor::ServiceDescriptor>::Method,
        input: bytes::Bytes,
    ) -> Self::CallFuture {
        // You can use information from the descriptors to include in the request:
        self.websocket.call(Self::Descriptor::name(), method.name(), input)
    }
}

现在你可以使用这个处理程序与 prost-simple-rpc 生成的客户端一起使用

fn main() {
    let websocket = WebSocketTransport::connect("...");
    let client = schema::echo::EchoClient::new(websocket);
    let future = client.echo(schema::echo::EchoRequest { /* ... */ });
    // ... use the future to wait for a response.
}

服务器

要创建你的服务服务器,首先实现为该服务生成的服务 trait

struct EchoService;

#[derive(Debug, Eq, Fail, PartialEq)]
#[fail(display = "Error!")]
struct Error;

impl schema::echo::Echo for EchoService {
    // You can supply an error type here if your service can fail.
    type Error = Error;
    // The future type used in the `echo()` method; you can of course use Box<Future<...>> here
    // but this library assumes unboxed futures by default.
    type EchoFuture = futures::future::FutureResult<schema::echo::EchoResponse, Self::Error>;

    fn echo(&self, input: schema::echo::EchoRequest) -> Self::EchoFuture {
        futures::future::ok(schema::echo::EchoResponse { data: input.data })
    }
}

现在,你可以用生成的服务器实现包装这个服务,以得到可以插入你首选路由系统中的内容

fn main() {
    let server = schema::echo::EchoServer::new(EchoService);
    
    websocket::spawn_server(move |request| {
        // You would probably normally look up the right method descriptor via some kind of routing
        // information; here's a hard-coded example:
        let method = schema::echo::EchoMethodDescriptor::Echo;

        server.call(method, request.data);
    });
}

lib.rs:

用于与 prost-simple-rpc 一起使用的代码生成库。

使用ServiceGeneratorprost-build生成代码。

extern crate prost_build;
extern crate prost_simple_rpc_build;

fn main() {
    prost_build::Config::new()
        .service_generator(Box::new(prost_simple_rpc_build::ServiceGenerator::new()))
        .compile_protos(&["test/example.proto"], &["test"])
        .unwrap();
}

依赖项

~9MB
~178K SLoC