如何用 Rust 實現 gRPC 服務

在本文中,將展示如何使用 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 }
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/k01C6K5ZV2WgPHzPN1yUmg