跳到主要内容

gRPC

问题

Rust 中如何使用 gRPC?

答案

tonic 是 Rust 的 gRPC 框架,基于 hyper 和 prost(Protobuf 实现)。

定义 Proto 文件

proto/hello.proto
syntax = "proto3";

package hello;

service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
rpc ServerStream (HelloRequest) returns (stream HelloReply);
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
}

服务端实现

src/server.rs
use tonic::{transport::Server, Request, Response, Status};
use hello::greeter_server::{Greeter, GreeterServer};
use hello::{HelloRequest, HelloReply};

pub mod hello {
tonic::include_proto!("hello"); // 编译时生成的代码
}

#[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 name = request.into_inner().name;
Ok(Response::new(HelloReply {
message: format!("Hello, {}!", name),
}))
}
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = "0.0.0.0:50051".parse()?;
Server::builder()
.add_service(GreeterServer::new(MyGreeter::default()))
.serve(addr)
.await?;
Ok(())
}

gRPC 四种通信模式

模式Proto 定义场景
一元rpc Fn(Req) returns (Resp)普通请求-响应
服务端流rpc Fn(Req) returns (stream Resp)推送数据
客户端流rpc Fn(stream Req) returns (Resp)上传数据
双向流rpc Fn(stream Req) returns (stream Resp)实时通信

常见面试问题

Q1: gRPC 相比 REST 有什么优势?

答案

维度gRPCREST
协议HTTP/2HTTP/1.1 or HTTP/2
序列化Protobuf(二进制)JSON(文本)
性能高(小体积、流式)一般
类型安全Proto 文件生成代码手动维护
流式通信原生支持需 SSE/WebSocket
浏览器支持需 grpc-web原生支持

gRPC 适合微服务内部通信,REST 适合面向外部客户端的 API。

相关链接