在 Rust 中 gRPC 使用的 protobuf 实现条件编译服务器和客户端(tonic)

前言

Rust 中 gRPC 最优秀的库是 tonic。tonic-build 的默认生成方式是生成一个带有数据类型和客户端与服务端源码,而对于分层应用,客户端尽可能不要知道服务端的代码,同时服务端也不应知道客户端的代码。这时条件编译就来了,来帮我们解决掉这个问题。

Cargo.toml 中设定 feature 条件

Cargo.toml 最后追加 features 标签,并加入 server 和 client 两种条件

[features]
server = []
client = []

build.rs 中使用条件

tonic 默认提供了一个示例方法,但他只能同时生成客户端和服务端。

/// 默认代码
fn main() -> Result<(), Box<dyn std::error::Error>> {
    tonic_build::compile_protos("proto/service.proto")?;
    Ok(())
}

进行一些小改动并添加进我们预先定义的条件

fn main() -> Result<(), Box<dyn std::error::Error>> {
    tonic_build::configure()
        // 编译服务端
        .build_server(cfg!(feature = "server"))
        // 编译客户端
        .build_client(cfg!(feature = "client"))
        // 在类型上增加 serde 用的 derive
        .type_attribute(
            ".",
            "#[derive(serde::Deserialize, serde::Serialize)] #[serde(rename_all = \"camelCase\")]",
        )
        // 编译
        .compile(&["proto/service.proto"], &["proto"])?;
    Ok(())
}

服务端调用

[dependencies]
app-protocol = { path = "../app-protocol", features = ["server"] }

参考

hyperium/tonic: A native gRPC client & server implementation with async/await support.

posted @ 2022-04-27 16:01  Aoba_xu  阅读(922)  评论(0编辑  收藏  举报