• 如何用Rust构建gRPC服务
  • 发布于 1周前
  • 129 热度
    0 评论
在本文中,将展示如何使用Rust和Proto协议创建一个简单的gRPC服务。
首先,我们运行以下命令来创建一个新的Rust应用程序:
cargo new rustgrpc
然后,在Cargo.toml文件中加入依赖项:
[dependencies]
tonic = "0.11"
tokio = { version = "1", features = ["full"] }
prost = "0.12.4"

[build-dependencies]
tonic-build = "0.11"
这个例子使用了Tonic库,它是gRPC的一个rust实现。它是一个快速、高性能、开源、通用的RPC框架,使用HTTP/2协议,支持移动端!我们已经定义了依赖项,现在可以继续编写应用程序了。

创建Proto文件
我们将创建Proto文件来处理请求消息和响应消息。Proto文件帮助客户端和服务器理解发送和接收的消息。在项目根目录下创建一个名为“protos”的新目录,并创建一个名为“hello.proto”的新文件。在文件中写入以下内容:
syntax = "proto3";
package hello;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}
语法声明了我们想要使用的proto版本,在本例中是最新版本proto3。package声明命名空间,在本例中为hello。接下来,我们定义接受HelloRequest(name)并返回HelloReply (message)的服务,为了简单起见,每个服务只声明一个变量。

既然已经定义了Proto文件,接下来我们需要创建一个构建文件。在项目根目录中创建一个名为“build.rs”的新文件,并用以下内容填充它:
fn main() -> Result<(), Box<dyn std::error::Error>> {
    tonic_build::compile_protos("protos/hello.proto")?;
    Ok(())
}
编写代码
在src/main.rs文件中,写入以下代码:
use tonic::{transport::Server, Request, Response, Status};

pub mod hello {
  tonic::include_proto!("hello");
}

use hello::{greeter_server::{Greeter, GreeterServer}, HelloReply, HelloRequest};
我们需要定义一个结构体来实现我们的服务,在上面的代码下面添加以下代码:
#[derive(Default)]
pub struct MyGreeter {}
接下来,我们需要创建一个实现来处理hello请求和响应:
#[tonic::async_trait]
impl Greeter for MyGreeter {
    async fn say_hello(
        &self,
        request: Request<HelloRequest>,
    ) -> Result<Response<HelloReply>, Status> {
        let reply = hello::HelloReply {
            message: format!("Hello {}!", request.into_inner().name),
        };
        Ok(Response::new(reply))
    }
}
这个函数接受一个HelloRequest并返回一个HelloReply,最后,我们在main函数中启动服务器并监听请求:
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let addr = "[::1]:50051".parse()?;
    let greeter = MyGreeter::default();

    Server::builder()
        .add_service(GreeterServer::new(greeter))
        .serve(addr)
        .await?;

    Ok(())
}
编写客户端程序
在src/bin/目录下,创建client.rs文件,在其中写入以下代码:
pub mod hello {
    tonic::include_proto!("hello");
}

use hello::{greeter_client::GreeterClient, HelloRequest};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = GreeterClient::connect("http://[::1]:50051").await?;

    let request = tonic::Request::new(HelloRequest {
        name: "Tonic".into(),
    });

    let response = client.say_hello(request).await?;

    println!("RESPONSE={:?}", response);

    Ok(())
}
运行应用程序
最后,我们需要做的就是构建和运行项目。
执行以下命令运行server端:
cargo run --bin rustgrpc
执行以下命令运行client端:
cargo run --bin client
如果一切正常,应该在client的终端中看到以下内容:
RESPONSE=Response { metadata: MetadataMap { headers: {"content-type": "application/grpc", "date": "", "grpc-status": "0"} }, message: HelloReply { message: "Hello Tonic!" }, extensions: Extensions }

用户评论