Skip to content

参考:gRPC 方法、状态码与 proto 演进速查

基于 gRPC 1.71 / protobuf proto3 · 核于 2026-08

速查

  • gRPC:Google 开源高性能 RPC,protobuf IDL + HTTP/2,跨 11+ 语言,CNCF 毕业项目(2018)。
  • protobuf:二进制序列化,tag-length-value 编码,字段名不存只存字段号,比 JSON 小 20%~70%。
  • HTTP/2:多路复用 + 二进制分帧 + HPACK + 双向流,是 gRPC 性能与流式调用的物理基础。
  • 四种方法:Unary(一问一答)、Server Streaming(一请求多响应)、Client Streaming(多请求一响应)、Bidirectional(双向流)。
  • Channel/Stub:Channel 是底层 HTTP/2 连接池(共享复用),Stub 是类型化客户端(由 proto 生成)。
  • Deadline:客户端超时,一路传递,生产必设(不设是反模式)。
  • metadata:HTTP/2 头部,键小写、不可 grpc- 开头、二进制值键 -bin 结尾。
  • 拦截器:客户端/服务端各 4 种(unary/server-stream/client-stream/bidi),用于 auth/log/metrics/trace。
  • 状态码:17 个标准码,grpc-status 在 trailer,比 HTTP 语义精细。
  • Connect:Buf 出品,一份 proto 出 gRPC/Connect/HTTP+JSON 三协议,浏览器原生无需 grpc-web。

一、四种服务方法速查

方法请求响应客户端代码服务端代码场景
Unary11stub.SayHello(req)Promise<Resp>async sayHello(req) → resp普通 API(90%)
Server Streaming1Nfor await (const r of call)while(...) yield r推送/分页/行情
Client StreamingN1call.write(...) × N → call.end()for await (const r of call)批量上传/攒批
BidirectionalNNcall.write/read 独立call.write/read 独立聊天/协同/实时
  • 顺序保证:同一 RPC 内,消息按发送顺序到达。
  • 取消:客户端随时 call.cancel(),服务端通过 context 感知。

二、gRPC 状态码清单

名称含义对应 HTTP 类比
0OK成功200
1CANCELLED客户端取消-
2UNKNOWN未知错误500
3INVALID_ARGUMENT参数非法400
4DEADLINE_EXCEEDED超时504
5NOT_FOUND资源不存在404
6ALREADY_EXISTS已存在409
7PERMISSION_DENIED无权限403
8RESOURCE_EXHAUSTED资源耗尽(配额/限流)429
9FAILED_PRECONDITION前置条件不满足400
10ABORTED并发冲突(可重试)409
11OUT_OF_RANGE超出范围400
12UNIMPLEMENTED方法未实现501
13INTERNAL内部错误500
14UNAVAILABLE服务不可用(可重试)503
15DATA_LOSS数据丢失-
16UNAUTHENTICATED未认证401
  • 可重试码(客户端可重试):UNAVAILABLEDEADLINE_EXCEEDED(部分场景)、ABORTEDRESOURCE_EXHAUSTED(限流)。
  • 不可重试码INVALID_ARGUMENTNOT_FOUNDPERMISSION_DENIED(重试也是错)。

三、proto3 演进规则

操作是否安全说明
新增字段旧客户端不传,新代码用默认值
删除字段必须 reserved N; 占号
改字段名按字段号解析,名无所谓
同 wire type 换类型int32↔uint32string↔bytes
复用已删字段号旧数据被误读,破坏兼容
单值改 repeatedwire type 语义冲突
改字段号等于删旧字段加新字段
改默认值默认值是语言规范定的,改不了

口诀:加字段随意、删字段 reserved、号不可复用、同 wire type 才能换类型。

四、拦截器场景与位置

场景客户端拦截器服务端拦截器
认证注入 auth header验证 token(注意:客户端 call credentials 更合适)
日志记录请求/响应记录调用
指标记录耗时/QPS记录耗时/错误率
链路追踪注入 traceparent开 span、关 span
重试失败自动重试-
限流-拒绝超额请求
缓存命中缓存直接返回-
  • 注意:拦截器只作用于单个 RPC 调用,管不了 TCP/TLS/端口——那是 ChannelOption 的活。

五、metadata 规则

规则说明
键大小写不敏感,建议全小写
键字符字母、数字、-_.
保留前缀grpc- 开头是框架保留(如 grpc-statusgrpc-encoding
ASCII 值键普通 key(如 authorization
二进制值键必须 -bin 结尾(如 trace-bin

六、gRPC over HTTP/2 速查

元素
:methodPOST
:path/{package}.{Service}/{Method}
:schemehttp / https
content-typeapplication/grpc(+ +proto / +json
tetrailers(必需)
grpc-encodingidentity / gzip / deflate / snappy
grpc-status在 trailer(响应尾部)
grpc-message错误消息(在 trailer)
消息前缀1B 压缩标志 + 4B 长度 + protobuf 体

七、易错点清单

  • 「gRPC 就是 protobuf」:错。gRPC 是 RPC 框架(管连接/调用/流式/状态码),protobuf 是序列化格式(管消息编码)。gRPC 默认用 protobuf,但理论上能用 JSON(application/grpc+json)。
  • 「HTTP/2 多路复用就一定快」:不一定。单连接多路复用在高并发小消息场景最优;超大文件传输(单流占满带宽)反而不如多连接。gRPC 默认单 Channel,必要时开多 Channel 负载均衡。
  • 「Unary 是流式的退化」:错。Unary 是独立的方法类型,有自己的调用流程和拦截器,不是「只发一条的流」。
  • 「proto 加字段要删旧客户端」:错。protobuf 向后兼容——加字段,旧客户端不传新字段,新代码用默认值,零影响。
  • 「字段号可以随便改」:错。字段号是 wire 编码的 key,改号等于删旧字段加新字段,破坏兼容。
  • 「gRPC 状态码就是 HTTP 状态码」:错。gRPC 有 17 个独立状态码,grpc-status 在 trailer,语义和 HTTP 不同(如 UNAVAILABLE=14 不是 HTTP 503 的 1:1 映射)。
  • 「浏览器可以直接调 gRPC」:错。浏览器 fetch 无法控制 HTTP/2 trailer 与伪头,必须用 grpc-web(代理)或 Connect(原生)。
  • 「Deadline 只是客户端的事」:错。Deadline 一路传递——服务端 handler 能查到剩余时间(context.deadline),据此决定是否提前返回,避免下游雪崩。
  • **「metadata 键可以大写」」:技术上大小写不敏感,但规范是小写。且 grpc- 前缀是框架保留,用户键不能用。
  • 「Connect 替代了 gRPC」:错。Connect 是 gRPC 的现代化补充(浏览器/JSON 友好),但完全兼容标准 gRPC 客户端——一份 proto 同时服务 gRPC 和 Connect,不是替代关系。

权威链接