| Crates.io | xrpc |
| lib.rs | xrpc |
| version | 0.1.40 |
| created_at | 2025-10-24 13:24:26.316336+00 |
| updated_at | 2025-12-08 04:03:54.152264+00 |
| description | Transport-agnostic RPC framework / 传输层无关的RPC框架 |
| homepage | https://github.com/i18n-site/rust/tree/dev/xrpc |
| repository | https://github.com/i18n-site/rust.git |
| max_upload_size | |
| id | 1898418 |
| size | 112,968 |
A framework for building transport-agnostic RPC services. It provides a set of traits and structures to abstract the underlying communication protocol, allowing developers to focus on business logic.
The core idea behind xrpc is the separation of concerns. An RPC call is broken down into distinct stages:
xrpc provides traits to standardize the second stage, while offering hooks and adapters for the first and third. This makes the core application logic independent of the transport layer. The call! macro automates logging, timing, and error handling, further simplifying the developer's task.
The primary components of xrpc are exposed in src/lib.rs.
trait Func: Defines the basic signature of an RPC function, associating Args and a Result type.trait Call / trait AsyncCall: Implement these traits for your synchronous or asynchronous RPC functions. You define the inner method, and the call method (provided by the call! macro) wraps it with logging, error handling, and metrics.struct ReqArgs: A wrapper that provides the inner method with the request context (including headers) and the parsed arguments.trait Req: Represents an incoming request, providing a method ext to access request-scoped extension data.trait Ext: A trait for extracting and initializing request-scoped data, such as user sessions or database connections, in a lazy-loaded fashion.enum Result<T>: A specialized result type for inner methods. It can be:
Ok(T): The operation was successful.Err(anyhow::Error): A generic error occurred. The framework will automatically convert this to a standard 500-level error response.Response(Response): The method needs to return a specific error response (e.g., a 404 Not Found).struct Response: Represents a direct error response with a status code and body.Since the project does not contain a tests/ directory, here is a conceptual example of how to define and use an RPC service with xrpc and volo-grpc.
First, define your service and its methods in a .proto file:
syntax = "proto3";
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
service Greeter {
rpc SayHello(HelloRequest) returns (HelloResponse);
}
Next, implement the AsyncCall trait for your SayHello RPC:
use xrpc::{AsyncCall, Func, ReqArgs, Result};
use your_generated_types::{HelloRequest, HelloResponse}; // Assuming types generated by prost/pilota
pub struct SayHello;
impl Func for SayHello {
type Args = HelloRequest;
type Result = HelloResponse;
fn name() -> &'static str {
"SayHello"
}
}
impl AsyncCall for SayHello {
async fn inner<H: Map, E: Ext>(req_args: ReqArgs<H, E, Self::Args>) -> Result<Self::Result> {
let message = format!("Hello, {}!", req_args.args.name);
Result::Ok(HelloResponse { message })
}
}
Finally, integrate it into your volo-grpc service implementation:
use volo_grpc::Request;
use xrpc::volo::grpc::{split, IntoResponse};
use xrpc::Call; // Use Call or AsyncCall
// Assuming a volo service struct
pub struct MyService;
#[volo::async_trait]
impl Greeter for MyService {
async fn say_hello(&self, req: Request<HelloRequest>) -> Result<Response<HelloResponse>, Status> {
// 1. Split the volo request into xrpc parts
let (req, args) = split(req);
// 2. Execute the xrpc call
let result = SayHello::call::<MyLogger, _, _>((&req, args)).await;
// 3. Convert the xrpc result back into a volo response
result.into_response()
}
}
/
├── Cargo.toml # Package manifest
├── AGENTS.md # Agent instructions
├── src/ # Source code
│ ├── lib.rs # Main library file, exports public APIs
│ ├── call.rs # Defines the core `Call` and `AsyncCall` traits
│ ├── response.rs # Defines the `Response` struct for direct error returns
│ ├── result.rs # Defines the `Result` enum for RPC outcomes
│ └── volo/ # Adapters for the Volo framework
│ ├── mod.rs
│ ├── grpc.rs # gRPC-specific helpers
│ └── http.rs # HTTP-specific helpers
└── readme/ # README files
├── en.md # English README
└── zh.md # Chinese README
Remote Procedure Calls (RPC) are a cornerstone of distributed systems. The concept originated in the 1970s, with one of the first major implementations being at Xerox PARC. The idea was simple yet powerful: make a function call on a remote machine look and feel like a local one.
The 1980s popularized the term, largely thanks to Sun Microsystems and their implementation used in the Network File System (NFS). This era was dominated by technologies like SunRPC (later ONC RPC) and DCE/RPC.
The rise of the web in the 2000s brought RPC to HTTP, with protocols like XML-RPC and SOAP (Simple Object Access Protocol). These used text-based formats (XML) for communication, which offered interoperability at the cost of performance.
Modern RPC, driven by the microservices boom, has shifted back towards high-performance binary protocols. Frameworks like Google's gRPC (which uses Protocol Buffers) and Apache Thrift dominate the landscape. They offer features essential for modern distributed applications, such as efficient serialization, streaming, and language independence, continuing the evolution of that initial idea from the 1970s.
This project is an open-source component of i18n.site ⋅ Internationalization Solution.
i18 : MarkDown Command Line Translation Tool
The translation perfectly maintains the Markdown format.
It recognizes file changes and only translates the modified files.
The translated Markdown content is editable; if you modify the original text and translate it again, manually edited translations will not be overwritten (as long as the original text has not been changed).
i18n.site : MarkDown Multi-language Static Site Generator
Optimized for a better reading experience
一个用于构建传输层无关RPC服务的框架。它提供一系列特性和结构来抽象底层通信协议,使开发者能专注于业务逻辑。
xrpc 的核心思想是关注点分离。一个RPC调用被分解为几个不同阶段:
xrpc 提供 traits 来标准化第二阶段,同时为第一和第三阶段提供钩子和适配器。这使得核心应用逻辑独立于传输层。call! 宏自动处理日志、计时和错误处理,进一步简化了开发者的任务。
xrpc 的主要组件在 src/lib.rs 中导出。
trait Func:定义RPC函数的基本签名,关联 Args 和 Result 类型。trait Call / trait AsyncCall:为同步或异步RPC函数实现这些 trait。你只需定义 inner 方法,而 call 方法(由 call! 宏提供)会用日志、错误处理和度量来包装它。struct ReqArgs:一个包装器,为 inner 方法提供请求上下文(包括头信息)和已解析的参数。trait Req:代表传入的请求,提供 ext 方法以访问请求范围的扩展数据。trait Ext:用于以懒加载方式提取和初始化请求范围数据的 trait,例如用户会话或数据库连接。enum Result<T>:为 inner 方法设计的专用结果类型。它可以是:
Ok(T):操作成功。Err(anyhow::Error):发生通用错误。框架会自动将其转换为标准的500级别错误响应。Response(Response):方法需要返回一个特定的错误响应(例如,404 Not Found)。struct Response:代表一个带有状态码和消息体的直接错误响应。由于项目不包含 tests/ 目录,这里是一个如何使用 xrpc 和 volo-grpc 定义和使用RPC服务的概念性示例。
首先,在 .proto 文件中定义你的服务及其方法:
syntax = "proto3";
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
service Greeter {
rpc SayHello(HelloRequest) returns (HelloResponse);
}
接下来,为 SayHello RPC实现 AsyncCall trait:
use xrpc::{AsyncCall, Func, ReqArgs, Result};
use your_generated_types::{HelloRequest, HelloResponse}; // 假设是由 prost/pilota 生成的类型
pub struct SayHello;
impl Func for SayHello {
type Args = HelloRequest;
type Result = HelloResponse;
fn name() -> &'static str {
"SayHello"
}
}
impl AsyncCall for SayHello {
async fn inner<H: Map, E: Ext>(req_args: ReqArgs<H, E, Self::Args>) -> Result<Self::Result> {
let message = format!("Hello, {}!", req_args.args.name);
Result::Ok(HelloResponse { message })
}
}
最后,将其集成到你的 volo-grpc 服务实现中:
use volo_grpc::Request;
use xrpc::volo::grpc::{split, IntoResponse};
use xrpc::Call; // 根据情况使用 Call 或 AsyncCall
// 假设的服务结构体
pub struct MyService;
#[volo::async_trait]
impl Greeter for MyService {
async fn say_hello(&self, req: Request<HelloRequest>) -> Result<Response<HelloResponse>, Status> {
// 1. 将 volo 请求拆分为 xrpc 部件
let (req, args) = split(req);
// 2. 执行 xrpc 调用
let result = SayHello::call::<MyLogger, _, _>((&req, args)).await;
// 3. 将 xrpc 结果转换回 volo 响应
result.into_response()
}
}
/
├── Cargo.toml # 包配置
├── AGENTS.md # Agent 指令
├── src/ # 源代码
│ ├── lib.rs # 主库文件,导出公共API
│ ├── call.rs # 定义核心的 `Call` 和 `AsyncCall` traits
│ ├── response.rs # 定义用于直接错误返回的 `Response` 结构体
│ ├── result.rs # 定义用于RPC结果的 `Result` 枚举
│ └── volo/ # Volo 框架的适配器
│ ├── mod.rs
│ ├── grpc.rs # gRPC 相关辅助函数
│ └── http.rs # HTTP 相关辅助函数
└── readme/ # README 文件
├── en.md # 英文 README
└── zh.md # 中文 README
远程过程调用(RPC)是分布式系统的基石。其概念起源于1970年代,最早的重要实现之一是在施乐帕洛阿尔托研究中心(Xerox PARC)。这个想法简单而强大:让远程机器上的函数调用看起来和感觉上都像本地调用一样。
1980年代,这个术语开始普及,主要归功于Sun Microsystems及其在网络文件系统(NFS)中的实现。那个时代由SunRPC(后来的ONC RPC)和DCE/RPC等技术主导。
2000年代互联网的兴起将RPC带入了HTTP,催生了XML-RPC和SOAP(简单对象访问协议)等协议。它们使用基于文本的格式(XML)进行通信,以性能为代价换取了互操作性。
在微服务浪潮的推动下,现代RPC已回归到高性能的二进制协议。像Google的gRPC(使用Protocol Buffers)和Apache Thrift等框架占据了主导地位。它们为现代分布式应用提供了必不可少的特性,如高效序列化、流处理和语言无关性,延续了1970年代最初那个想法的演进之路。
本项目为 i18n.site ⋅ 国际化解决方案 的开源组件。
翻译能够完美保持 Markdown 的格式。能识别文件的修改,仅翻译有变动的文件。
Markdown 翻译内容可编辑;如果你修改原文并再次机器翻译,手动修改过的翻译不会被覆盖 ( 如果这段原文没有被修改 )。
i18n.site : MarkDown 多语言静态站点生成器 为阅读体验而优化。