Rust使用gRPC

Rust
370
0
0
2024-03-24
标签   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(())
}

编译和运行

  1. 在server项目根目录执行cargo run来编译和运行项目,服务器将启动并监听在[::1]:50051

  1. 在client项目根目录执行cargo run来编译和运行项目,客户端将发送一个请求并打印出服务端的响应内容

参考资料

[1]

Protobuf Compiler Installation: https://github.com/protocolbuffers/protobuf