Week 3 · Chapter 2 · gRPC 与 Protobuf
复习难度:⭐⭐⭐ | 预计时长:2-3小时 | 重点程度:中
为什么选 gRPC
HTTP/1.1 → 队头阻塞(同一TCP连接只能串行请求)
HTTP/2 → 多路复用(一个TCP连接并行多个请求)
gRPC → 基于 HTTP/2 + Protobuf(二进制序列化,比 JSON 小 3-6 倍)
你的 IAM 系统用 gRPC-Gateway 同时暴露 HTTP 和 gRPC 接口。
Protobuf 基本语法
syntax = "proto3";
package user;
service UserService {
rpc GetUser(GetUserRequest) returns (UserResponse);
rpc ListUsers(ListUsersRequest) returns (stream UserResponse); // 服务端流
}
message GetUserRequest {
string user_id = 1; // 字段编号,不是字段名
int32 page_size = 2 [default = 10];
}
message UserResponse {
string id = 1;
string name = 2;
string email = 3;
map<string, string> metadata = 4; // map 类型
repeated string roles = 5; // 数组
}
注意:字段编号是协议升级时唯一稳定的标识,改字段名不影响序列化。
gRPC 拦截器
// unary interceptor( unary = 单次请求响应)
func AuthInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
// 从 metadata 取 token
md, ok := metadata.FromIncomingContext(ctx)
if !ok { return nil, status.Error(codes.Unauthenticated, "no metadata") }
token := md["authorization"]
if !validateToken(token) { return nil, status.Error(codes.Unauthenticated, "invalid token") }
return handler(ctx, req)
}
服务端流和客户端流拦截器写法类似,用 grpc.StreamServerInterceptor。
面试重点
Q:gRPC 和 REST 的区别?
① 序列化:Protobuf vs JSON(二进制 vs 文本) ② 传输协议:HTTP/2 vs HTTP/1.1 ③ 接口定义:.proto 文件强类型 vs OpenAPI 弱类型 ④ 流支持:原生支持服务端/客户端/双向流
Q:gRPC 的缺点?
① 调试不如 HTTP/REST 方便(不能用浏览器直接测试) ② 穿透防火墙不如 HTTP(有些代理不认识) ③ 学习成本比 REST 高
Q:你为什么选 gRPC-Gateway?
内部服务用 gRPC 高性能,外部系统(如审批回调)用 HTTP 方便接入,一次定义同时暴露两种接口。