gRPC:跑在 HTTP/2 上的高性能 RPC
gRPC 是 Google 开源、CNCF 托管的高性能 RPC(远程过程调用)框架:用 Protocol Buffers 定义服务接口与消息(IDL),生成多语言客户端/服务端桩代码,底层默认且强依赖 HTTP/2 传输。它在微服务间通信中常被用来替代 REST+JSON。
一、为什么是 HTTP/2
gRPC 的很多能力直接来自 HTTP/2(见该篇):
- 单连接多路复用:一次调用就是 HTTP/2 上的一个 stream,多个并发调用复用同一条 TCP 连接、帧交错传输,没有 HTTP/1.1 的队头阻塞与多连接握手开销,也不必为每条 RPC 开连接。
- 二进制分帧 + 头部压缩:gRPC 消息放进 HTTP/2 DATA 帧,方法/元数据走 HPACK 压缩的头部,比文本 HTTP/1.1 高效。
- 双向流:HTTP/2 天然支持双向数据流,支撑 gRPC 的 streaming 调用。
- 长连接:通常保持少量长连接(channel),通过负载均衡策略在其上分发调用。
注意仍受 HTTP/2 的 TCP 层队头阻塞影响:底层一个 TCP 段丢失会卡住所有并发 stream(gRPC 也不例外);要彻底解决需 HTTP/3/QUIC(已有 gRPC-over-HTTP3 的实验/演进,见 HTTP/3)。
二、Protobuf:紧凑的接口与序列化
用 .proto 以契约方式定义:
syntax = "proto3";
service UserService {
rpc GetUser(GetUserReq) returns (User); // 一元
rpc Watch(WatchReq) returns (stream Event); // 服务端流
rpc Upload(stream Chunk) returns (Ack); // 客户端流
rpc Chat(stream Msg) returns (stream Msg); // 双向流
}
message GetUserReq { int64 id = 1; }- 字段以编号标识、二进制编码,比 JSON 更小、编解码更快、跨语言强类型。
- 契约先行,
protoc+ 插件生成服务端接口和客户端 SDK,前后端/多语言协作时类型与兼容性靠字段编号管理(加字段用新编号即可向后兼容)。 - 代价:二进制不可肉眼直读(抓包需解析)、对浏览器不直接友好(需 gRPC-Web 转码或 Connect/REST 网关)。
三、四种调用模式
| 模式 | 方向 | 适用 |
|---|---|---|
| 一元 unary | 请求→响应,一次往返 | 普通查询/命令,类似普通 RPC |
| 服务端流 server streaming | 一请求,多响应 | 推送、订阅、大结果集分块、实时事件 |
| 客户端流 client streaming | 多请求,一响应 | 上传分片、聚合提交 |
| 双向流 bidi streaming | 双方持续发 | 聊天、遥测上报、长连接交互 |
stream 不是新协议,只是在同一个 HTTP/2 stream 上反复收发"长度前缀的 gRPC 消息帧"(5 字节头:1 字节压缩标志 + 4 字节长度,后接 Protobuf body)——应用层仍需明确消息边界,思路与 TCP 粘包分帧一致,但这里由 HTTP/2 帧和 gRPC 长度前缀共同界定。
四、工程要点
- 状态码与状态:gRPC 有自己的状态码(OK/DEADLINE_EXCEEDED/UNAVAILABLE…),映射到 HTTP/2 的 200 + grpc-status 尾部(trailers)。
- 截止时间 deadline / 超时:调用应带 deadline,在整条调用链上传播,避免上游等待无限放大。
- 拦截器 interceptor:类似中间件,统一做认证、日志、重试、指标(RED)、tracing(可观测性是 gRPC 微服务的强项)。
- 取消与传播:客户端取消会沿 HTTP/2 RST_STREAM 传播到服务端。
- 负载均衡:可在客户端做(连接级/请求级),或经 L7 代理(Envoy)。注意 gRPC 长连接复用使简单 L4 轮询可能把流量压在少数连接上,常需 L7 感知。
- 安全:常配合 TLS(HTTP/2 over TLS)。
五、和 REST/JSON 怎么选
| 维度 | gRPC | REST/JSON |
|---|---|---|
| 场景 | 内部微服务、多语言、高 QPS、流式 | 对外开放 API、浏览器直接访问、缓存友好 |
| 序列化 | Protobuf 紧凑二进制、强类型 | JSON 文本、灵活可读 |
| 契约 | .proto 严格、代码生成 | OpenAPI 可选 |
| 传输 | 强依赖 HTTP/2、长连接多路复用 | HTTP/1.1/2 均可 |
| 调试 | 需工具(grpcurl、反射) | curl 即可 |
| 浏览器 | 需 gRPC-Web/网关 | 原生 |
经验:服务间内部通信、追求性能与强契约、需要流式用 gRPC;面向公网、需浏览器直连与 HTTP 缓存用 REST/JSON,或两者并存(gRPC 对内 + 网关转 REST/JSON 对外)。
相关阅读
底座见 HTTP/2 多路复用 与 HTTP/3/QUIC,重试/幂等见方法幂等,长连接心跳见 WebSocket,压测可结合网络工具篇。
总结
gRPC 用 Protobuf 做契约化强类型、二进制紧凑序列化,并把每次调用映射为 HTTP/2 上的一个 stream,从而在少量长连接上多路复用、HPACK 压缩头部、天然支持一元与三种流式调用,配合 deadline、拦截器和状态码适合内部微服务高性能通信;代价是强依赖 HTTP/2、二进制不直观、浏览器需 gRPC-Web,对外开放 API 仍常用 REST/JSON。