Rust JSON-RPC服务器库jsonrpsee-http-server的使用:构建高性能HTTP RPC服务的Rust插件库

Rust JSON-RPC服务器库jsonrpsee-http-server的使用:构建高性能HTTP RPC服务的Rust插件库

安装

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

cargo add jsonrpsee-http-server

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

jsonrpsee-http-server = "0.15.1"

完整示例代码

use jsonrpsee_http_server::{HttpServerBuilder, RpcModule};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 创建HTTP服务器
    let server = HttpServerBuilder::default()
        .build("127.0.0.1:9944")
        .await?;

    // 创建RPC模块
    let mut module = RpcModule::new(());
    
    // 注册RPC方法
    module.register_method("say_hello", |_, _| {
        Ok("Hello, world!")
    })?;

    // 注册RPC模块
    server.register_module(module)?;

    // 启动服务器
    server.start().await?;

    Ok(())
}

使用方法

  1. 首先创建HTTP服务器实例,指定监听地址和端口
  2. 创建一个RpcModule实例来注册RPC方法
  3. 使用register_method方法注册RPC方法
  4. 将模块注册到服务器
  5. 启动服务器

文档

官方文档 源代码仓库

许可证

MIT许可证

所有者

  • paritytech/Core devs团队
  • Niklas Adolfsson
  • Parity Crate Owner
  • Parity CI Robot

完整示例代码

以下是一个更完整的示例,展示了如何创建一个带有多个RPC方法的JSON-RPC服务器:

use jsonrpsee_http_server::{HttpServerBuilder, RpcModule};
use serde_json::Value;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 创建HTTP服务器,监听本地9944端口
    let server = HttpServerBuilder::default()
        .build("127.0.0.1:9944")
        .await?;

    // 创建RPC模块
    let mut module = RpcModule::new(());
    
    // 注册简单的问候方法
    module.register_method("greet", |params, _| {
        let name: String = params.parse()?;
        Ok(format!("Hello, {}!", name))
    })?;

    // 注册带参数的加法方法
    module.register_method("add", |params, _| {
        let (a, b): (i32, i32) = params.parse()?;
        Ok(a + b)
    })?;

    // 注册获取服务器信息的方法
    module.register_method("get_server_info", |_, _| {
        Ok(serde_json::json!({
            "name": "jsonrpsee-http-server",
            "version": "0.15.1"
        }))
    })?;

    // 将模块注册到服务器
    server.register_module(module)?;

    println!("Server started at http://127.0.0.1:9944");
    
    // 启动服务器
    server.start().await?;

    Ok(())
}

这个示例展示了:

  1. 创建多个RPC方法
  2. 处理不同类型的参数
  3. 返回不同类型的数据
  4. 使用serde_json返回结构化数据

要测试这个服务器,可以使用任何JSON-RPC客户端向http://127.0.0.1:9944发送请求。


1 回复

Rust JSON-RPC服务器库jsonrpsee-http-server的使用指南

简介

jsonrpsee-http-server是一个高性能的Rust库,用于构建JSON-RPC 2.0规范的HTTP服务器。它是jsonrpsee生态系统的一部分,专注于提供简单易用且高性能的RPC服务实现。

主要特性

  • 完全兼容JSON-RPC 2.0规范
  • 异步支持(基于tokio)
  • 类型安全的RPC方法注册
  • 中间件支持
  • 低开销和高性能

使用方法

1. 添加依赖

首先在Cargo.toml中添加依赖:

[dependencies]
jsonrpsee-http-server = "0.16"
tokio = { version = "1.0", features = ["full"] }

2. 基本示例

use jsonrpsee_http_server::{RpcModule, ServerBuilder};
use std::net::SocketAddr;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 创建RPC模块
    let mut module = RpcModule::new(());
    
    // 注册RPC方法
    module.register_method("say_hello", |_, _| {
        Ok("Hello from JSON-RPC!")
    })?;
    
    // 注册带参数的方法
    module.register_method("add", |params, _| {
        let (a, b): (i32, i32) = params.parse()?;
        Ok(a + b)
    })?;
    
    // 构建服务器
    let server = ServerBuilder::default()
        .build("127.0.0.1:9944")
        .await?;
    
    // 启动服务器
    let addr = server.local_addr()?;
    println!("Server running at {}", addr);
    
    // 等待服务器关闭
    server.start(module).await?;
    
    Ok(())
}

3. 带上下文的高级示例

use jsonrpsee_http_server::{RpcModule, ServerBuilder};
use std::sync::Arc;

struct MyContext {
    shared_data: String,
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let ctx = Arc::new(MyContext {
        shared_data: "some shared state".to_string(),
    });
    
    let mut module = RpcModule::new(ctx);
    
    module.register_method("get_shared_data", |_, ctx| {
        Ok(ctx.shared_data.clone())
    })?;
    
    module.register_method("echo", |params, _| {
        let input: String = params.parse()?;
        Ok(input)
    })?;
    
    let server = ServerBuilder::default()
        .build("127.0.0.1:9944")
        .await?;
    
    println!("Server running at {}", server.local_addr()?);
    server.start(module).await?;
    
    Ok(())
}

4. 订阅方法示例

jsonrpsee-http-server也支持发布-订阅模式:

use jsonrpsee_http_server::{RpcModule, ServerBuilder, SubscriptionSink};
use jsonrpsee_core::Error;
use tokio::sync::broadcast;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let (tx, _) = broadcast::channel(16);
    
    let mut module = RpcModule::new(tx);
    
    module.register_subscription("subscribe_events", "subscribe", "unsubscribe", |mut sink, tx| async move {
        let mut rx = tx.subscribe();
        
        while let Ok(event) = rx.recv().await {
            if let Err(err) = sink.send(&event) {
                eprintln!("Failed to send event: {}", err);
                break;
            }
        }
        
        Ok(())
    })?;
    
    let server = ServerBuilder::default()
        .build("127.极客时间Rust训练营0.0.1:9944")
        .await?;
    
    println!("Server running at {}", server.local_addr()?);
    server.start(module).await?;
    
    Ok(())
}

配置选项

ServerBuilder提供了多种配置选项:

let server = ServerBuilder::default()
    .max_request_body_size(1024 * 1024) // 1MB
    .max_response_body_size(1024 * 1024) // 1MB
    .set_http_middleware(/* 自定义中间件 */)
    .cors(/* CORS配置 */)
    .build("127.0.0.1:9944")
    .await?;

客户端调用示例

使用curl测试服务器:

# 调用say_hello方法
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"say_hello","id":1}' http://localhost:9944

# 调用add方法
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"add","params":[2,3],"id":1}' http://localhost:9944

性能优化建议

  1. 使用Arc共享大型上下文数据
  2. 对于CPU密集型任务,考虑使用tokio::task::spawn_blocking
  3. 合理设置请求和响应体大小限制
  4. 使用连接池管理下游服务连接

jsonrpsee-http-server是一个强大而灵活的库,可以轻松构建高性能的JSON-RPC服务。通过合理设计RPC接口和利用Rust的类型系统,可以创建既安全又高效的远程过程调用服务。

完整示例代码

下面是一个完整的JSON-RPC服务器示例,包含基本方法、上下文共享和订阅功能:

use jsonrpsee_http_server::{RpcModule, ServerBuilder, SubscriptionSink};
use jsonrpsee_core::Error;
use std::sync::Arc;
use tokio::sync::broadcast;

// 定义共享的上下文
struct AppState {
    counter: u64,
    event_tx: broadcast::Sender<String>,
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 创建事件广播通道
    let (event_tx, _) = broadcast::channel(16);
    
    // 创建共享上下文
    let ctx = Arc::new(AppState {
        counter: 0,
        event_tx,
    });
    
    // 创建RPC模块
    let mut module = RpcModule::new(ctx.clone());
    
    // 注册简单方法
    module.register_method("greet", |params, _| {
        let name: String = params.parse().unwrap_or("world".into());
        Ok(format!("Hello, {}!", name))
    })?;
    
    // 注册带状态的方法
    module.register_method("increment", |_, ctx| {
        let mut ctx = Arc::make_mut(&mut Arc::clone(&ctx));
        ctx.counter += 1;
        Ok(ctx.counter)
    })?;
    
    // 注册订阅方法
    module.register_subscription(
        "events", 
        "subscribe_events", 
        "unsubscribe_events", 
        |mut sink, ctx| async move {
            let mut rx = ctx.event_tx.subscribe();
            
            // 发送初始事件
            if let Err(e) = sink.send(&"Subscription started".to_string()) {
                eprintln!("Failed to send initial event: {}", e);
                return Ok(());
            }
            
            // 处理事件流
            while let Ok(event) = rx.recv().await {
                if let Err(e) = sink.send(&event) {
                    eprintln!("Failed to send event: {}", e);
                    break;
                }
            }
            
            Ok(())
        },
    )?;
    
    // 启动后台任务发送事件
    tokio::spawn(async move {
        let mut count = 0;
        loop {
            tokio::time::sleep(std::time::Duration::from_secs(1)).await;
            count += 1;
            let _ = ctx.event_tx.send(format!("Event {}", count));
        }
    });
    
    // 构建并启动服务器
    let server = ServerBuilder::default()
        .max_request_body_size(1024 * 1024)
        .build("127.0.0.1:9944")
        .await?;
    
    println!("Server running at {}", server.local_addr()?);
    server.start(module).await?;
    
    Ok(())
}

这个完整示例展示了:

  1. 基本RPC方法调用
  2. 共享状态的修改
  3. 发布-订阅模式
  4. 后台任务生成事件
  5. 服务器配置选项

您可以使用curl测试这些端点:

# 测试greet方法
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"greet","params":["Rust"],"id":1}' http://localhost:9944

# 测试increment方法
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"increment","id":1}' http://localhost:9944

# 测试订阅(使用websocket客户端)
回到顶部