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 有什么优势?
答案:
| 维度 | gRPC | REST |
|---|---|---|
| 协议 | HTTP/2 | HTTP/1.1 or HTTP/2 |
| 序列化 | Protobuf(二进制) | JSON(文本) |
| 性能 | 高(小体积、流式) | 一般 |
| 类型安全 | Proto 文件生成代码 | 手动维护 |
| 流式通信 | 原生支持 | 需 SSE/WebSocket |
| 浏览器支持 | 需 grpc-web | 原生支持 |
gRPC 适合微服务内部通信,REST 适合面向外部客户端的 API。