Rust JSON-RPC库op-alloy-rpc-jsonrpsee的使用,支持高效异步RPC通信与Alloy框架集成

op-alloy-rpc-jsonrpsee

CI op-alloy-rpc-jsonrpsee crate MIT License Apache License Book

低层级的Optimism JSON-RPC服务器和客户端实现。

元数据

包:cargo/op-alloy-rpc-jsonrpsee@0.19.0

大约6小时前

版本:1.86.0

许可证:MIT OR Apache-2.0

大小:16.2 KiB

安装

在您的项目目录中运行以下Cargo命令:

cargo add op-alloy-rpc-jsonrpsee

或者在您的Cargo.toml中添加以下行:

op-alloy-rpc-jsonrpsee = “0.19.0”

文档

文档地址

仓库

代码仓库地址

所有者

alloy-rs/core Matthias Seitz refcell clabby Emilia Hane

完整示例demo:

// Cargo.toml
[dependencies]
op-alloy-rpc-jsonrpsee = "0.19.0"
jsonrpsee = { version = "0.19", features = ["server", "client", "http-client", "http-server", "ws-client", "ws-server"] }
tokio = { version = "1.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

// main.rs
use jsonrpsee::{
    server::ServerBuilder,
    core::Error,
    http_client::{HttpClient, HttpClientBuilder},
    proc_macros::rpc,
};
use op_alloy_rpc_jsonrpsee::{
    optimism::{OptimismApiServer, OptimismApi},
    types::*,
};
use std::net::SocketAddr;

// 定义RPC方法
#[rpc(server, client)]
pub trait MyOptimismApi {
    #[method(name = "my_customMethod")]
    async fn my_custom_method(&self, param: String) -> Result<String, Error>;
}

// 实现RPC方法
pub struct MyOptimismApiImpl;

impl MyOptimismApiServer for MyOptimismApiImpl {
    async fn my_custom_method(&self, param: String) -> Result<String, Error> {
        Ok(format!("Received: {}", param))
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建服务器
    let server_addr: SocketAddr = "127.0.0.1:9944".parse().unwrap();
    let server = ServerBuilder::default()
        .build(server_addr)
        .await?;
    
    let api = MyOptimismApiImpl;
    let server_handle = server.start(api.into_rpc())?;
    
    // 创建客户端
    let client = HttpClientBuilder::default()
        .build("http://127.0.0.1:9944")?;
    
    let client = MyOptimismApiClient::new(client);
    
    // 调用RPC方法
    let response = client.my_custom_method("test_param".to_string()).await?;
    println!("Server response: {}", response);
    
    // 保持服务器运行
    server_handle.stopped().await;
    
    Ok(())
}

1 回复

Rust JSON-RPC库op-alloy-rpc-jsonrpsee使用指南

概述

op-alloy-rpc-jsonrpsee是一个专为Rust设计的JSON-RPC库,提供高效的异步RPC通信能力,并与Alloy框架深度集成。该库基于jsonrpsee构建,支持客户端和服务器端的RPC通信,特别适合需要高性能异步处理的区块链和分布式应用场景。

主要特性

  • 完全异步设计,基于async/await语法
  • 与Alloy框架无缝集成
  • 支持HTTP和WebSocket传输协议
  • 类型安全的RPC方法调用
  • 可扩展的中间件系统

安装方法

在Cargo.toml中添加依赖:

[dependencies]
op-alloy-rpc-jsonrpsee = "0.1"
tokio = { version = "1.0", features = ["full"] }

基本使用方法

1. 创建RPC服务器

use op_alloy_rpc_jsonrpsee::server::{ServerBuilder, ServerHandle};
use jsonrpsee::core::Error;
use jsonrpsee::proc_macros::rpc;

#[rpc(server)]
pub trait MyRpc {
    #[method(name = "say_hello")]
    async fn say_hello(&self, name: String) -> Result<String, Error>;
}

struct MyRpcServer;

impl MyRpcServer for MyRpcServer {
    async fn say_hello(&self, name: String) -> Result<String, Error> {
        Ok(format!("Hello, {}!", name))
    }
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let server = ServerBuilder::default()
        .build("127.0.0.1:9944")
        .await?;
    
    let handle = server.start(MyRpcServer.into_rpc())?;
    
    handle.stopped().await;
    Ok(())
}

2. 创建RPC客户端

use op_alloy_rpc_jsonrpsee::client::ClientBuilder;
use jsonrpsee::core::client::ClientT;
use jsonrpsee::rpc_params;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let client = ClientBuilder::default()
        .build("http://127.0.0.1:9944")
        .await?;
    
    let response: String = client
        .request("say_hello", rpc_params!["World"])
        .await?;
    
    println!("Server response: {}", response);
    Ok(())
}

3. 与Alloy框架集成示例

use op_alloy_rpc_jsonrpsee::alloy_integration::AlloyRpcExt;
use alloy::providers::ProviderBuilder;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 创建支持JSON-RPC的Alloy Provider
    let provider = ProviderBuilder::new()
        .with_jsonrpc_client("http://localhost:8545")
        .await?;
    
    // 使用Alloy框架的标准方法
    let block_number = provider.get_block_number().await?;
    println!("Current block number: {}", block_number);
    
    Ok(())
}

高级功能

自定义中间件

use op_alloy_rpc_jsonrpsee::middleware::{Middleware, Next};
use jsonrpsee::core::server::rpc_module::Methods;

struct LoggingMiddleware;

impl Middleware for LoggingMiddleware {
    async fn call(&self, request: &str, next: Next<'_>) -> Result<String, Error> {
        println!("Received request: {}", request);
        let response = next.call(request).await;
        println!("Sending response: {:?}", response);
        response
    }
}

// 在服务器构建时添加中间件
let server = ServerBuilder::default()
    .with_middleware(LoggingMiddleware)
    .build("127.0.0.1:9944")
    .await?;

批量请求处理

use op_alloy_rpc_jsonrpsee::client::BatchRequestBuilder;

let batch = BatchRequestBuilder::new()
    .add_request("method1", rpc_params![1, 2, 3])
    .add_request("method2", rpc_params!["test"])
    .build();

let results: Vec<serde_json::Value> = client.batch_request(batch).await?;

错误处理

use op_alloy_rpc_jsonrpsee::error::RpcError;

match client.request("some_method", rpc_params![]).await {
    Ok(result) => println!("Success: {:?}", result),
    Err(RpcError::RequestTimeout) => eprintln!("Request timed out"),
    Err(RpcError::TransportError(e)) => eprintln!("Transport error: {}", e),
    Err(e) => eprintln!("Other error: {}", e),
}

性能优化建议

  1. 使用连接池管理客户端连接
  2. 合理配置超时时间
  3. 启用压缩减少网络传输
  4. 使用批处理请求减少网络往返

这个库为Rust开发者提供了强大的JSON-RPC功能,特别适合需要高性能异步通信和与Alloy框架集成的应用场景。

完整示例代码

以下是一个完整的RPC服务器和客户端交互示例:

Cargo.toml

[package]
name = "op-alloy-rpc-demo"
version = "0.1.0"
edition = "2021"

[dependencies]
op-alloy-rpc-jsonrpsee = "0.1"
jsonrpsee = { version = "0.18", features = ["server", "client", "macros"] }
tokio = { version = "1.0", features = ["full"] }
anyhow = "1.0"
serde_json = "1.0"

src/main.rs

use op_alloy_rpc_jsonrpsee::server::{ServerBuilder, ServerHandle};
use op_alloy_rpc_jsonrpsee::client::ClientBuilder;
use jsonrpsee::core::Error;
use jsonrpsee::proc_macros::rpc;
use jsonrpsee::core::client::ClientT;
use jsonrpsee::rpc_params;

// 定义RPC trait
#[rpc(server)]
pub trait DemoRpc {
    #[method(name = "greet")]
    async fn greet(&self, name: String) -> Result<String, Error>;
    
    #[method(name = "add")]
    async fn add(&self, a: i32, b: i32) -> Result<i32, Error>;
}

// 实现RPC服务器
struct DemoRpcServer;

impl DemoRpcServer for DemoRpcServer {
    async fn greet(&self, name: String) -> Result<String, Error> {
        Ok(format!("Hello, {}! Welcome to JSON-RPC", name))
    }
    
    async fn add(&self, a: i32, b: i32) -> Result<i32, Error> {
        Ok(a + b)
    }
}

// 服务器端代码
async fn run_server() -> anyhow::Result<ServerHandle> {
    println!("Starting RPC server on 127.0.0.1:9944...");
    
    let server = ServerBuilder::default()
        .build("127.0.0.1:9944")
        .await?;
    
    let handle = server.start(DemoRpcServer.into_rpc())?;
    
    println!("Server started successfully!");
    Ok(handle)
}

// 客户端代码
async fn run_client() -> anyhow::Result<()> {
    println!("Connecting to RPC server...");
    
    let client = ClientBuilder::default()
        .build("http://127.0.0.1:9944")
        .await?;
    
    // 单个请求示例
    let greeting: String = client
        .request("greet", rpc_params!["Alice"])
        .await?;
    println!("Greeting response: {}", greeting);
    
    let sum: i32 = client
        .request("add", rpc_params![5, 3])
        .await?;
    println!("Addition result: 5 + 3 = {}", sum);
    
    // 批量请求示例
    use op_alloy_rpc_jsonrpsee::client::BatchRequestBuilder;
    
    let batch = BatchRequestBuilder::new()
        .add_request("greet", rpc_params!["Bob"])
        .add_request("add", rpc_params![10, 20])
        .build();
    
    let results: Vec<serde_json::Value> = client.batch_request(batch).await?;
    println!("Batch results: {:?}", results);
    
    Ok(())
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 启动服务器
    let server_handle = run_server().await?;
    
    // 等待服务器完全启动
    tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
    
    // 运行客户端测试
    if let Err(e) = run_client().await {
        eprintln!("Client error: {}", e);
    }
    
    // 关闭服务器
    server_handle.stop()?;
    server_handle.stopped().await;
    
    println!("Demo completed successfully!");
    Ok(())
}

运行说明:

  1. 将上述代码保存到项目中
  2. 运行 cargo run 启动示例
  3. 程序将自动启动服务器、执行客户端请求并显示结果

这个完整示例展示了:

  • RPC服务器的创建和启动
  • RPC客户端的连接和请求
  • 单个方法和批量请求的使用
  • 完整的错误处理和资源清理
回到顶部