43 个版本 (破坏性更新)

0.34.0 2023 年 12 月 30 日
0.33.0 2023 年 4 月 3 日
0.32.0 2023 年 3 月 24 日
0.31.0 2022 年 11 月 3 日
0.3.0 2016 年 2 月 20 日

#26 in 网络编程

Download history 29406/week @ 2024-04-23 24854/week @ 2024-04-30 26003/week @ 2024-05-07 26279/week @ 2024-05-14 20317/week @ 2024-05-21 26062/week @ 2024-05-28 27026/week @ 2024-06-04 27647/week @ 2024-06-11 23943/week @ 2024-06-18 25904/week @ 2024-06-25 23586/week @ 2024-07-02 25477/week @ 2024-07-09 25165/week @ 2024-07-16 29429/week @ 2024-07-23 26949/week @ 2024-07-30 32189/week @ 2024-08-06

118,190 每月下载量
用于 265 个 Crates (42 直接使用)

MIT 许可证

240KB
5K SLoC

Crates.io MIT licensed Build status Discord chat

tarpc

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

tarpc 是一个专注于易用性的 Rust RPC 框架。定义一个服务只需几行代码,并且服务器的大部分样板代码都由您负责。

文档

什么是 RPC 框架?

"RPC" 代表 "远程过程调用",是一种在别处执行生成返回值的工作的过程调用。当调用 RPC 函数时,后台会联系其他进程并请求它们执行该函数。原始函数随后返回其他进程生成的值。

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

tarpc 与其他 RPC 框架的区别在于,它通过代码定义模式,而不是在单独的语言(如 .proto)中定义。这意味着没有单独的编译过程,也不需要在不同的语言之间切换上下文。

tarpc 的其他一些功能

  • 可插拔的传输:任何实现了 Stream<Item = Request> + Sink<Response> 的类型都可以用作连接客户端和服务器传输。
  • Send + 'static 可选:如果传输不需要它,tarpc 也不需要!
  • 级联取消:取消一个请求将向服务器发送一个取消消息。服务器将停止该请求的所有未完成的工作,然后取消其自己的任何请求,并重复对整个传递依赖链的操作。
  • 可配置的截止时间和截止时间传播:如果未指定,请求截止时间为10秒。当截止时间过去时,服务器将自动停止工作。服务器发送的任何使用请求上下文的请求都会传播请求截止时间。例如,如果一个服务器正在处理一个10秒截止时间的请求,做了2秒的工作,然后向另一个服务器发送请求,那么该服务器将看到8秒的截止时间。
  • 分布式跟踪:tarpc 使用 tracing 原语,这些原语通过 OpenTelemetry 跟踪进行了扩展。使用兼容的跟踪订阅者,如 Jaeger,每个RPC都可以通过客户端、服务器以及服务器下游的其他依赖项进行跟踪。即使是未连接到分布式跟踪收集器的应用程序,跟踪工具也可以被常规的日志记录器,如 env_logger,所消费。
  • Serde 序列化:启用 serde1 Cargo 功能将使服务请求和响应可序列化和反序列化。虽然这是完全可选的,但也可以使用内存中的传输,因此不需要时无需支付序列化的代价。

使用方法

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

tarpc = "0.34"

tarpc::service 属性扩展为一个由形成 rpc 服务的项目集合。这些生成的类型使得编写服务器变得更加简单和直观。只需实现生成的服务特质,然后您就可以开始比赛了!

示例

此示例使用 tokio,因此请将以下依赖项添加到您的 Cargo.toml

anyhow = "1.0"
futures = "0.3"
tarpc = { version = "0.31", features = ["tokio1"] }
tokio = { version = "1.0", features = ["rt-multi-thread", "macros"] }

在以下示例中,我们使用进程内通道在客户端和服务器之间进行通信。在实际代码中,您可能会通过网络进行通信。有关更实际的示例,请参阅 example-service

首先,让我们设置依赖项和服务定义。

use futures::future::{self, Ready};
use tarpc::{
    client, context,
    server::{self, Channel},
};

// 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]
trait World {
    /// Returns a greeting for name.
    async fn hello(name: String) -> String;
}

此服务定义生成一个名为 World 的特质。接下来我们需要为我们的 Server 结构体实现它。

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

impl World 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}!"))
    }
}

最后,让我们编写 main,该程序将启动服务器。虽然此示例使用进程内通道,但 tarpc 还在 serde-transport 功能之后提供了一个通用的 serde_transport,在 tcp 功能之后提供了额外的 TCP 功能。

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let (client_transport, server_transport) = tarpc::transport::channel::unbounded();

    let server = server::BaseChannel::with_defaults(server_transport);
    tokio::spawn(server.execute(HelloServer.serve()));

    // WorldClient is generated by the #[tarpc::service] attribute. It has a constructor `new`
    // that takes a config and any Transport as input.
    let client = WorldClient::new(client::Config::default(), client_transport).spawn();

    // The client has an RPC method for each RPC defined in the annotated trait. 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 = client.hello(context::current(), "Stim".to_string()).await?;

    println!("{hello}");

    Ok(())
}

服务文档

使用与通常相同的 cargo doc,查看由 service! 调用展开的所有项目创建的文档。

许可证:MIT

依赖项

~7–17MB
~205K SLoC