8个版本
使用旧Rust 2015
0.3.0 | 2018年8月7日 |
---|---|
0.2.1 | 2018年4月2日 |
0.1.5 | 2018年4月2日 |
0.1.1 | 2018年3月31日 |
#1276 在 编码
20KB
189 行
prost-simple-rpc
你是否想使用类型安全的基于Protobuf的RPC,而不需要使用像gRPC这样的重量级工具?
这个库允许你生成特性行为,以使用Protobuf作为模式语言实现通用的RPC机制。你必须提供自己的底层传输机制,例如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;
}
使用 prost
、prost-build
和 prost-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.
}
服务器
要为你的服务创建一个服务器,首先实现生成的服务特性行为。
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);
});
}
依赖关系
~1.9–4MB
~86K SLoC