与 REST/GraphQL 对比与 Connect
基于 gRPC 1.71 / Connect 1.x · 核于 2026-08
速查
- 三大 API 风格:①REST(资源 + HTTP 动词 + JSON,无契约、人可读、浏览器友好,公网/第三方首选);②gRPC(protobuf 契约 + HTTP/2,强类型、流式、高性能,服务间内部首选);③GraphQL(Schema + 单端点按需取字段,解决 over/under-fetching,聚合层/BFF 首选)。
- gRPC vs REST 核心差异:①契约——gRPC 强(proto 编译期校验)vs REST 弱(OpenAPI 可选);②序列化——protobuf 二进制(小 20%~70%、快 5~10 倍)vs JSON 文本;③传输——HTTP/2 多路复用 vs HTTP/1.1(REST 多用);④流式——gRPC 四种原生流 vs REST 仅请求-响应(SSE/WebSocket 另算);⑤浏览器——gRPC 不友好(需 grpc-web 网关)vs REST 原生。
- gRPC vs GraphQL:①gRPC 是「方法导向」(调 sayHello)vs GraphQL 是「数据导向」(查询字段);②gRPC 走 HTTP/2 二进制 vs GraphQL 多走 HTTP/1.1 JSON;③GraphQL 强在聚合多数据源给前端按需取,gRPC 强在服务间高频低延迟调用。
- 选型口诀:内部服务间通信 → gRPC(性能/契约/流式);公网 API / 第三方 / 移动端 → REST(通用/可读/缓存);前端聚合多后端 → GraphQL(按需取/避免多次往返)。
- gRPC 浏览器痛点:浏览器 fetch 不能直接控制 HTTP/2 trailer、不能自定义
:method等 HTTP/2 伪头——gRPC 无法在浏览器裸跑。解法:①grpc-web(Envoy 代理转码 HTTP/1.1 → HTTP/2,加一层);②grpc-gateway(proto 生成 REST 网关,双协议)。 - Connect(Buf 出品):2022 年发布的「更好的 gRPC」——一份 proto,三协议输出(gRPC / Connect / HTTP+JSON)。Connect 协议跑在 HTTP/1.1 或 HTTP/2 上,浏览器原生支持、无需 grpc-web 代理,既兼容标准 gRPC 客户端,又能给前端用 JSON。
- Connect 协议特点:①支持 unary 和流式;②HTTP/1.1 + HTTP/2 都能跑(gRPC 只能 HTTP/2);③既可传 protobuf 二进制,也可传 JSON;④错误用标准化的 JSON Error 对象表达(不依赖 trailer)。
- 何时用 Connect:需要前端直连后端 RPC(省 grpc-web 网关)、想要 JSON + protobuf 双格式、想要 HTTP/1.1 兼容(老旧基础设施)。内部纯后端用标准 gRPC 即可。
- 生态对比:gRPC(CNCF 毕业项目,2018,生态最广)/ Connect(Buf 主导,2022,现代浏览器友好)/ tRPC(TS 全栈,无 IDL 跨语言,仅限 TS)。
一、三大 API 风格:REST、gRPC、GraphQL
| 维度 | REST | gRPC | GraphQL |
|---|---|---|---|
| 导向 | 资源(名词 + HTTP 动词) | 方法(动词,调 RPC) | 数据(查询字段) |
| 契约 | 无(OpenAPI 可选) | 强(proto,编译期) | 强(Schema,编译期) |
| 序列化 | JSON(文本) | protobuf(二进制) | JSON(文本) |
| 传输 | HTTP/1.1(多为) | HTTP/2 | HTTP(多为 1.1) |
| 流式 | 请求-响应(SSE/WS 另算) | 四种原生流 | 订阅(WebSocket) |
| 浏览器 | 原生友好 | 需 grpc-web 网关 | 原生友好 |
| 典型场景 | 公网 API / 第三方 / 移动端 | 服务间内部通信 | 前端聚合层 / BFF |
| 性能 | 中(JSON 大、多连接) | 高(二进制、多路复用) | 中(N+1 查询要 DataLoader) |
| 可读性 | 高(curl 直接看) | 低(二进制要解码) | 中(query 字符串) |
一句话:REST 给人和公网用、gRPC 给服务间用、GraphQL 给前端按需取用——三者互补,不是替代。
二、gRPC vs REST:性能与契约的取舍
性能差距的来源
- 序列化:protobuf 比 JSON 小 20%~70%(字段名不存)、解析快 5~10 倍(二进制 tag 直接索引 vs 字符串解析)。对高频小消息(如每秒上万次服务调用),差距显著。
- 连接:gRPC 一个 HTTP/2 连接多路复用 N 个 RPC;REST/HTTP/1.1 要么开多 TCP 连接(握手开销)、要么 HTTP/1.1 keep-alive 串行(队头阻塞)。
- 延迟:综合下来,gRPC 端到端延迟通常比 REST 低 30%~70%(视 payload 大小和并发度)。
契约的取舍
- gRPC 强契约:proto 是单一事实来源,改 proto → 重新生成 → 编译器立刻报出所有不兼容的地方。团队多语言、契约演进频繁时,这是巨大优势。
- REST 弱契约:JSON 没有内置 schema,OpenAPI/Swagger 是「文档化」而非「强制」。字段加错了运行时才崩。
REST 不死的原因
- 可读性:curl + 浏览器 DevTools 直接看 JSON,调试零门槛。gRPC 要 grpcurl / postman gRPC / 抓包解码。
- 通用性:公网第三方集成、移动端、CDN 缓存、SEO——REST 是行业默认。
- 基础设施:老旧 Nginx / 反向代理 / WAF 对 HTTP/2 流式和 trailer 支持参差不齐,gRPC 要额外配置。
三、gRPC vs GraphQL:方法导向 vs 数据导向
- gRPC 是「调方法」:
stub.GetUser(id)——服务端定义方法,客户端调。适合「我要执行一个动作」(下单、转账、推送)。 - GraphQL 是「查字段」:
query { user(id:1) { name posts { title } } }——客户端声明要哪些字段,服务端返回刚好这些。适合「我要一堆关联数据,且不同页面要不同子集」。 - 互补场景:GraphQL 常做 BFF(Backend For Frontend),背后聚合多个 gRPC 服务——前端发 GraphQL,BFF 转成 gRPC 调内部服务,兼顾「前端按需取」和「后端高性能」。
四、gRPC 的浏览器痛点:grpc-web 与 grpc-gateway
gRPC 跑在 HTTP/2 上,需要客户端能控制 HTTP/2 trailer、自定义伪头——浏览器的 fetch/XHR 做不到。所以 gRPC 不能在浏览器裸跑,要靠中介:
- grpc-web(官方):Envoy/特制代理把浏览器的 HTTP/1.1 请求转成 HTTP/2 gRPC 调用。前端用
grpc-web客户端库。代价:多一层代理、流式支持有限(客户端流和双向流支持受限)。 - grpc-gateway(插件):从 proto 生成一个 REST 网关,把 HTTP/JSON 请求转成 gRPC 调用。好处:一套服务暴露双协议(REST 给前端 + gRPC 给内部);代价:要维护生成代码、性能有转码损耗。
这两个方案都「能用」,但都不优雅——这正是 Connect 要解决的。
五、Connect:一份 proto,三协议输出
Connect 是 Buf 公司 2022 年发布的 RPC 框架,定位「更好的 gRPC」。核心理念:一份 proto 定义,同时生成 gRPC、Connect、HTTP/JSON 三种协议的客户端和服务端。
.proto (单一事实来源)
│
┌────────────────┼────────────────┐
▼ ▼ ▼
gRPC 协议 Connect 协议 HTTP/JSON
(HTTP/2 二进制) (HTTP/1.1 或 2) (REST 友好)
│ │ │
内部服务互通 浏览器直连 第三方/移动端
(标准 gRPC) (无需 grpc-web) (curl 可调试)Connect 协议的关键设计
- HTTP/1.1 + HTTP/2 都能跑:不强制 HTTP/2,老旧基础设施(Nginx/CDN/Serverless)兼容。
- 浏览器原生:前端用 fetch 直接调,不需要 grpc-web 代理——这是最大卖点。
- 二进制 + JSON 双格式:同一个端点,客户端可以传 protobuf(高性能)或 JSON(可读),服务端按 Content-Type 自动解析。
- 错误用 JSON Error 对象:不依赖 HTTP/2 trailer(gRPC 把状态码放 trailer,浏览器读不到),改用标准化的 JSON 错误体,前端友好。
- 支持流式:unary / server-stream / client-stream / bidi 都支持(HTTP/2 上全支持,HTTP/1.1 上用 chunked transfer 做服务端流)。
Connect vs gRPC vs grpc-web
| 维度 | gRPC | grpc-web | Connect |
|---|---|---|---|
| 传输 | HTTP/2 only | HTTP/1.1(代理转 HTTP/2) | HTTP/1.1 + HTTP/2 |
| 浏览器 | 不支持 | 需 Envoy 代理 | 原生支持 |
| 序列化 | protobuf | protobuf | protobuf + JSON |
| 代理 | 不需要 | 需要 | 不需要 |
| 错误处理 | trailer 状态码 | trailer(转码) | JSON Error 对象 |
| 流式 | 全支持 | 受限 | 全支持 |
何时用 Connect
- 前端直连后端 RPC:省掉 grpc-web 网关这一层,降低架构复杂度。
- 需要 JSON + protobuf 双格式:内部用 protobuf、外部用 JSON,一份 proto 搞定。
- HTTP/1.1 基础设施:Serverless、老旧 CDN、特定 Ingress 不支持 HTTP/2 流式时。
- 纯后端内部通信:用标准 gRPC 即可,Connect 的优势(浏览器/JSON)用不上。
六、选型决策树
这个 API 的消费者是谁?
│
├─ 内部服务(后端 ↔ 后端)
│ └─→ gRPC(性能 + 契约 + 流式)
│ └─ 跨语言团队?gRPC 跨 11+ 语言,杀手锏
│
├─ 浏览器 / 移动端 直连
│ ├─ 想要 RPC 体验 + 强契约 → Connect(省 grpc-web)
│ └─ 通用 / 第三方友好 → REST + JSON
│
├─ 前端聚合多后端(按需取字段)
│ └─→ GraphQL(BFF 层,背后可调 gRPC)
│
└─ 公网开放 API(第三方集成)
└─→ REST(行业默认,OpenAPI 文档)下一步
掌握了 gRPC 的协议、方法、对比与 Connect 后,可回到参考查四种方法速查、状态码清单、proto 演进规则与易错点。