Rust 使用 gRPC
需要先安裝 protoc(Protocol Buffers Compiler),可據此 Protobuf Compiler Installation[1] 下載
第一步:創建項目
-
創建兩個新的 Rust 項目,分別作爲服務端與客戶端:
cargo new rust_grpc_server cargo new rust_grpc_client
-
分別在項目根目錄創建
proto
文件夾,並在其中創建一個叫hello.proto
的文件
第二步:編寫.proto
文件
在proto/hello.proto
文件中分別寫入以下內容:
syntax = "proto3";
package hello;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings.
message HelloReply {
string message = 1;
}
第三步:添加依賴
在 server 的項目的Cargo.toml
文件中添加以下依賴:
[dependencies]
tonic = "0.6"
tokio = { version = "1", features = ["full"] }
prost = "0.9"
[build-dependencies]
tonic-build = "0.6"
在 client 的項目的Cargo.toml
文件中添加以下依賴:
[dependencies]
tonic = "0.6"
tokio = { version = "1", features = ["full"] }
prost = "0.9"
rand = "0.8"
[build-dependencies]
tonic-build = "0.6"
第四步:創建 build 腳本
分別在根目錄創建一個build.rs
文件,添加以下代碼, 根據.proto
文件生成相應的 Rust 代碼:
fn main() {
tonic_build::compile_protos("proto/hello.proto")
.expect("Failed to compile proto files");
}
最終生成的代碼類似
第五步:編寫 gRPC 服務器
在 server 項目的src/main.rs
中,創建一個 gRPC 服務器:
use std::time::SystemTime;
use tonic::{transport::Server, Request, Response, Status};
pub mod hello {
tonic::include_proto!("hello");
}
use hello::greeter_server::{Greeter, GreeterServer};
use hello::{HelloReply, HelloRequest};
#[derive(Default)]
pub struct MyGreeter {}
#[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 {}!,Current Time is {:?}",
request.into_inner().name,
SystemTime::now()
),
};
Ok(Response::new(reply))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = "[::1]:50051".parse()?;
let greeter = MyGreeter::default();
println!("GreeterServer listening on {}", addr);
Server::builder()
.add_service(GreeterServer::new(greeter))
.serve(addr)
.await?;
Ok(())
}
第六步:編寫 gRPC 客戶端
在 client 項目的src/main.rs
文件中,添加一個客戶端來測試服務器:
use rand::Rng;
pub mod hello {
tonic::include_proto!("hello");
}
use hello::HelloRequest;
#[derive(Default)]
pub struct MyGreeter {}
// 客戶端代碼
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 客戶端測試
let mut client = hello::greeter_client::GreeterClient::connect("http://[::1]:50051").await?;
// 隨機選擇一個字符串出來
let names = ["張三", "李四", "王五"];
let mut rng = rand::thread_rng();
let random_name = names[rng.gen_range(0..names.len())];
let request = tonic::Request::new(HelloRequest {
name: random_name.into(),
});
let response = client.say_hello(request).await?;
println!("RESPONSE={:?}", response.into_inner().message);
Ok(())
}
編譯和運行
- 在 server 項目根目錄執行
cargo run
來編譯和運行項目,服務器將啓動並監聽在[::1]:50051
- 在 client 項目根目錄執行
cargo run
來編譯和運行項目,客戶端將發送一個請求並打印出服務端的響應內容
參考資料
[1]
Protobuf Compiler Installation: https://github.com/protocolbuffers/protobuf
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/a_v6_F6nqGlDcBUKyEQF2w