如何用Rust实现gRPC服务

401次阅读  |  发布于7月以前

在本文中,将展示如何使用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 }

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8