gRPC 是一种高性能远程过程调用框架,让一个程序像调用本地方法一样调用另一台机器上的服务方法,并用 schema 生成跨语言客户端和服务端代码。

核心问题

分布式系统里的服务通常运行在不同进程、机器或语言环境中。调用方希望表达的是“调用 SayHello(name) 得到 HelloReply”,但网络上实际只能传输字节、连接状态和错误码。gRPC 解决的是把远程服务抽象成类型化方法,同时把编码、连接、状态码、超时和流控收敛到统一框架里。

核心对象

对象作用工程关注点
.proto 文件定义消息类型和 service 方法字段编号、兼容性、包名
Message请求或响应的数据结构类型、字段编号、默认值、未知字段
Service一组可远程调用的方法方法名、输入类型、输出类型
Client stub客户端本地代理对象timeout、metadata、重试、连接复用
Server implementation服务端真实处理逻辑并发、鉴权、错误映射
Channel客户端到服务端的逻辑连接连接池、TLS、负载均衡
StatusRPC 调用结果OK、超时、不可用、权限错误

核心机制

一个最小 gRPC service 通常写成:

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}
 
message HelloRequest {
  string name = 1;
}
 
message HelloReply {
  string message = 1;
}

机制可以拆成四步:

  1. 开发者在 .proto 中定义消息和 service。
  2. protoc 和 gRPC 插件生成客户端 stub、服务端接口和 Protocol Buffers 编解码代码。
  3. 客户端调用本地 stub 方法;stub 把请求对象序列化成 protobuf 字节,并通过基于 HTTP/2 的传输发送。
  4. 服务端收到请求后反序列化,分发到实现方法,返回响应消息和 status。

这里“像本地调用”只是编程模型,不是运行时事实。真实调用仍然跨网络,会遇到超时、连接断开、重试导致的重复请求、服务端部分失败和版本兼容问题。

gRPC 支持多种调用形态:

  • Unary RPC:一个请求对应一个响应,OTLP/gRPC 的 export 请求就属于这个直觉。
  • Server streaming:一个请求对应多个响应。
  • Client streaming:多个请求汇成一个响应。
  • Bidirectional streaming:双方都可以持续发送消息。

工程用途

  • 微服务之间的高吞吐、低延迟内部 API。
  • 多语言服务接口,借助生成代码减少手写客户端。
  • 强 schema 的控制面或数据面协议。
  • 遥测、配置、网关和 Agent 之间的二进制传输,例如 OTLP/gRPC。

观察 gRPC 系统时,重点看请求延迟、status code 分布、deadline exceeded、unavailable、重试次数、连接数、消息大小和服务端并发。

边界与常见坑

  • gRPC 不是 REST:它用 service/method 建模,不以资源 URL 和 HTTP verb 作为核心抽象。
  • 本地调用只是表象:远程调用必须显式设计 timeout、幂等、重试和错误处理。
  • proto 字段编号不能随便改:字段名可以生成不同语言代码,但 wire format 依赖字段编号。
  • 浏览器支持需要额外考虑:传统 gRPC 基于 HTTP/2 语义,浏览器场景常需要 gRPC-Web 或网关。
  • 流式能力不等于无限缓冲:streaming 仍受流控、队列、内存和服务端处理速度限制。
  • 认证不应只靠内网假设:生产环境需要 TLS、mTLS、token 或网关策略来建立调用方身份。

相关术语

外部参考