跳转至

Wire Protocol 与数据帧规范

gRPC 的通信规约建立在 HTTP/2 之上,官方称之为 gRPC over HTTP/2 Wire Protocol。它精确定义了请求路由、长度前缀帧封装、超时表示法以及响应尾部状态传递的标准。


1. 长度前缀消息封装(Length-Prefixed Framing)

在 HTTP/2 的 DATA 帧中,传输的并不是纯裸的 Protobuf 序列化字节,而是包裹了一层 5 字节前缀的复合结构:

+------------------+-----------------------------------+-----------------------------+
| Compressed (1B)  |       Message Length (4B)         |    Serialized Message (NB)  |
+------------------+-----------------------------------+-----------------------------+

字段细节

  1. Compressed-Flag(1 字节)
  2. 0:未压缩,紧接着的数据即为原始 Protobuf 序列化二进制流。
  3. 1:已启用压缩(采用请求头 grpc-encoding 中协商的算法,如 gzipsnappyzstd)。
  4. Message Length(4 字节,大端序 Big-Endian)
  5. 32 位无符号整型,精确指明后续 Protobuf 消息载荷的实际字节大小 $N$。
  6. Serialized Message($N$ 字节)
  7. 实际传输的应用层数据实体。

[!NOTE] 流式解包的关键:通过这个固定 5 字节的头部,无论是客户端流还是双向流,接收端都能够精确地在连续的字节流中切分(Framing)出一个个独立的 Protobuf 对象,彻底解决了 TCP 粘包和拆包问题。


2. 请求阶段规范(Request Protocol)

gRPC 客户端发起请求时,必须通过一个带 END_HEADERS 的 HTTP/2 HEADERS 帧启动一个新流(Stream):

伪头部(Pseudo-Headers)

  • :method:必须固定为 POST
  • :schemehttphttps
  • :path:格式严格为 /{PackageName}.{ServiceName}/{MethodName}
  • 示例/helloworld.Greeter/SayHello
  • :authority:目标服务器地址与端口(如 api.example.com:443)。

标准 gRPC 头部

  • content-type:必须为 application/grpc(或者追加子类型 application/grpc+protoapplication/grpc+json)。
  • te:必须包含 trailers(告知代理和对端允许接收 HTTP/2 Trailers 尾部帧)。
  • grpc-timeout:请求截止超时时间,格式由数值和一个时间单位字符组成:
  • H(小时)、M(分钟)、S(秒)、m(毫秒)、u(微秒)、n(纳秒)。
  • 示例grpc-timeout: 500m(超时 500 毫秒)。
  • grpc-encoding:期望的消息压缩编码(如 gzip)。

3. 响应阶段与 Trailers 设计

gRPC 将响应划分为两个阶段: 1. Initial-Metadata(响应头):通过第一个 HEADERS 帧返回 :status: 200 和自定义业务头。 2. Response Data(响应体):通过一个或多个 DATA 帧传输带长度前缀的响应消息。 3. Trailing-Metadata(响应尾):通过最后一个带 END_STREAM 标志的 HEADERS 帧传输。gRPC 的调用状态码与错误信息正是位于此处!

sequenceDiagram
    participant Client as 客户端
    participant Server as 服务端

    Client->>Server: HEADERS (:method=POST, :path=/svc/method)
    Client->>Server: DATA (5B前缀 + Request Payload, END_STREAM)
    Server-->>Client: HEADERS (:status=200, content-type=application/grpc)
    Server-->>Client: DATA (5B前缀 + Response Payload)
    Server-->>Client: HEADERS (grpc-status=0, grpc-message=OK, END_STREAM)

Trailers 核心字段

  • grpc-status:gRPC 标准状态码(0 代表 OK,4 代表 DEADLINE_EXCEEDED 等)。
  • grpc-message:经 URL 百分号编码的错误提示字符串。
  • grpc-status-details-bin:携带二进制 Protobuf 富错误对象(包含更为丰富的结构化错误细节)。

4. Trailers-Only 优化机制

如果服务端在收到请求进行校验时发现错误(例如鉴权失败或资源不存在),根本无需写入任何响应体数据。

此时 gRPC 会触发 Trailers-Only 极速优化:服务端直接返回单个包含 END_STREAM 标志的 HEADERS 帧,将 HTTP 状态码与 gRPC 状态合并发送:

HTTP/2 200 OK
content-type: application/grpc
grpc-status: 16 (UNAUTHENTICATED)
grpc-message: Missing or invalid authorization token
[END_STREAM]

这避免了先发头部、再发空数据、再发尾部的三次帧往返损耗,极大提升了错误场景下的系统防御吞吐量。