#tarpc #rpc #bincode #networking #serde

nightly tarpc-bincode-transport

tarpc 服务的基于 bincode 的传输

6 个版本 (破坏性更新)

0.7.0 2019 年 5 月 11 日
0.6.0 2019 年 4 月 30 日
0.5.0 2019 年 4 月 16 日
0.4.0 2019 年 3 月 27 日
0.1.0 2018 年 10 月 17 日

#23 in #bincode

MIT 许可证

115KB
2.5K SLoC

tarpc: Tim & Adam 的 RPC 库

Travis-CI Status Software License Latest Version Join the chat at https://gitter.im/tarpc/Lobby

免责声明:这不是一个官方的 Google 产品。

tarpc 是一个专注于易用性的 Rust RPC 框架。定义一个服务只需要几行代码,大多数编写服务器的样板代码都由框架自动处理。

文档

什么是 RPC 框架?

"RPC" 代表 "远程过程调用",是一种函数调用,其中生成返回值的操作在其他地方进行。当调用 RPC 函数时,在幕后,函数会联系其他地方的某个进程,请求它们评估该函数。原始函数随后返回其他进程生成的值。

RPC 框架是大多数面向微服务的架构的基本构建块。其中两个著名的框架是 gRPCCap'n Proto

tarpc 与其他 RPC 框架的不同之处在于,它通过代码定义模式,而不是使用如 .proto 这样的单独语言。这意味着没有单独的编译过程,也不需要在不同语言之间进行认知上下文切换。此外,它还与社区支持的库 serde 一起工作:任何 serde 序列化的类型都可以用作 tarpc 函数的参数。

用法

将以下依赖项添加到您的 Cargo.toml

tarpc = "0.18.0"

service! 宏扩展为形成一个 RPC 服务的项目集合。在上面的示例中,该宏在 hello_service 模块中被调用。此模块将包含一个 Client 模板和 Service 特性。这些生成的类型使得编写服务器变得简单而直观,无需直接处理序列化。只需实现生成的特性之一,您就可以开始编写服务了!

示例

这是一个小型服务。

#![feature(arbitrary_self_types, await_macro, async_await, proc_macro_hygiene)]


use futures::{
    compat::Executor01CompatExt,
    future::{self, Ready},
    prelude::*,
};
use tarpc::{
    client, context,
    server::{self, Handler},
};
use std::io;

// This is the service definition. It looks a lot like a trait definition.
// It defines one RPC, hello, which takes one arg, name, and returns a String.
tarpc::service! {
    /// Returns a greeting for name.
    rpc hello(name: String) -> String;
}

// This is the type that implements the generated Service trait. It is the business logic
// and is used to start the server.
#[derive(Clone)]
struct HelloServer;

impl Service for HelloServer {
    // Each defined rpc generates two items in the trait, a fn that serves the RPC, and
    // an associated type representing the future output by the fn.

    type HelloFut = Ready<String>;

    fn hello(self, _: context::Context, name: String) -> Self::HelloFut {
        future::ready(format!("Hello, {}!", name))
    }
}

async fn run() -> io::Result<()> {
    // bincode_transport is provided by the associated crate bincode-transport. It makes it easy
    // to start up a serde-powered bincode serialization strategy over TCP.
    let transport = bincode_transport::listen(&"0.0.0.0:0".parse().unwrap())?;
    let addr = transport.local_addr();

    // The server is configured with the defaults.
    let server = server::new(server::Config::default())
        // Server can listen on any type that implements the Transport trait.
        .incoming(transport)
        // Close the stream after the client connects
        .take(1)
        // serve is generated by the service! macro. It takes as input any type implementing
        // the generated Service trait.
        .respond_with(serve(HelloServer));

    tokio_executor::spawn(server.unit_error().boxed().compat());

    let transport = await!(bincode_transport::connect(&addr))?;

    // new_stub is generated by the service! macro. Like Server, it takes a config and any
    // Transport as input, and returns a Client, also generated by the macro.
    // by the service mcro.
    let mut client = await!(new_stub(client::Config::default(), transport))?;

    // The client has an RPC method for each RPC defined in service!. It takes the same args
    // as defined, with the addition of a Context, which is always the first arg. The Context
    // specifies a deadline and trace information which can be helpful in debugging requests.
    let hello = await!(client.hello(context::current(), "Stim".to_string()))?;

    println!("{}", hello);

    Ok(())
}

fn main() {
    tarpc::init(tokio::executor::DefaultExecutor::current().compat());
    tokio::run(run()
            .map_err(|e| eprintln!("Oh no: {}", e))
            .boxed()
            .compat(),
    );
}

服务文档

与平常一样使用 cargo doc 来查看由 service! 调用扩展的所有项目的文档。

依赖

~8.5MB
~148K SLoC