在本文中,将展示如何使用Rust和Proto协议创建一个简单的gRPC服务。
cargo new rustgrpc
[dependencies]
tonic = "0.11"
tokio = { version = "1", features = ["full"] }
prost = "0.12.4"
[build-dependencies]
tonic-build = "0.11"
创建Proto文件
我们将创建Proto文件来处理请求消息和响应消息。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)的服务,为了简单起见,每个服务只声明一个变量。
fn main() -> Result<(), Box<dyn std::error::Error>> {
tonic_build::compile_protos("protos/hello.proto")?;
Ok(())
}
编写代码
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 {}
#[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))
}
}
#[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(())
}
编写客户端程序
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(())
}
运行应用程序
最后,我们需要做的就是构建和运行项目。
cargo run --bin rustgrpc
cargo run --bin client
RESPONSE=Response { metadata: MetadataMap { headers: {"content-type": "application/grpc", "date": "", "grpc-status": "0"} }, message: HelloReply { message: "Hello Tonic!" }, extensions: Extensions }