REST vs GraphQL vs gRPC:后端 API 协议选型的决策框架(2026)
三种主流 API 协议各有清晰的适用区间:REST 适合面向外部的资源型接口,GraphQL 适合多端聚合与快速迭代的前台,gRPC 适合内部服务间的高性能调用。本文给出一个按"调用方是谁"划分的决策框架,附典型组合架构与三个反模式。
先说结论
选协议的第一问不是”哪个先进”,而是**“调用方是谁”**:
| 调用方 | 首选 | 理由 |
|---|---|---|
| 外部开发者 / 第三方集成 | REST + OpenAPI | 生态兼容性、文档工具链、认知成本最低 |
| 自家多端前台(Web/App/小程序) | GraphQL(BFF 层) | 一次请求聚合多资源,前端迭代不等后端 |
| 内部服务之间 | gRPC | 强契约(protobuf)、低延迟、流式支持 |
成熟系统不是三选一,而是按接口边界分层混用。下面讲清每个协议的真实优劣与组合方式。
1. REST:默认选项的地位没有动摇
REST 的核心优势不在技术而在生态:OpenAPI 规范撑起了文档(Swagger UI)、Mock、契约测试、SDK 生成、API 网关策略的完整工具链;任何语言任何团队都能立刻上手。
适用区间:资源型 CRUD、对外开放 API、Webhook、需要 HTTP 缓存语义的场景。
真实短板:多资源聚合要么多次往返、要么后端写聚合接口(然后聚合接口越写越多,逐渐失控)——这正是 GraphQL 要解决的问题。
工程底线(无论选不选 REST 都适用):契约先行(OpenAPI 文档先于实现)、版本策略明确(URL 版本或 Header 版本,选一种坚持)、错误结构统一。
2. GraphQL:前台聚合层的利器,不是后端的替代品
GraphQL 的正确位置是 BFF(Backend for Frontend)层:前端按页面需要声明数据形状,一次请求拿全,后端不用为每个页面写聚合接口。多端形态差异大(Web 要全量、App 要精简、小程序要极简)时收益最大。
代价要说清楚:
- N+1 查询是默认会发生的(resolver 逐条取数),DataLoader 批量合并是必配项而非可选项;
- 缓存复杂化:HTTP 缓存基本失效(都是 POST /graphql),要靠客户端规范化缓存(Apollo/urql)或持久化查询;
- 失控查询风险:必须在网关层限制查询深度/复杂度,否则一个深层嵌套查询就是一次小型 DoS。
如果你的前台只有一个 Web 端、页面数据形状稳定——GraphQL 的收益撑不起这些复杂度,REST 就好。
3. gRPC:内部调用的性能与契约之王
protobuf 二进制序列化 + HTTP/2 多路复用,延迟和吞吐都显著优于 JSON over HTTP/1.1;.proto 文件是强类型契约,跨语言代码生成开箱即用;原生支持四种流式模式(一元、服务端流、客户端流、双向流),实时数据管道场景几乎没有对手。
边界也清晰:浏览器不能直连(需 gRPC-Web + 代理)、二进制报文人眼不可读(调试要 grpcurl/反射)、对外开放 API 用它会赶走一半集成方。
它是内部高速公路,不是对外的门面。
4. 典型组合架构
外部开发者 ──REST(OpenAPI)──┐
├─ API 网关 ──┐
Web/App/小程序 ─GraphQL(BFF)─┘ ├─ 服务A ─┐
├─ 服务B ─┼─ gRPC 互调
└─ 服务C ─┘
网关层做认证、限流、协议转换;BFF 层做聚合与裁剪;服务间走 gRPC。每层职责单一,替换任何一层都不动其他层。
三个反模式
- 用 GraphQL 做服务间调用——服务间不需要”灵活的数据形状”(契约本该稳定),却引入了 N+1 和缓存复杂度;这是 gRPC 的主场。
- 对外 API 用 gRPC 彰显技术——集成方的痛苦会变成你的售前成本。
- REST 接口”GraphQL 化”——
GET /users?fields=a,b,c&include=orders.items这种伪灵活查询,把两边的缺点集齐了:既没有 GraphQL 的类型系统,又丢了 REST 的缓存语义。要灵活就正经上 GraphQL,要简单就守住资源边界。
相关阅读
- AI Token 贸易平台架构:多供应商聚合与撮合 —— API 网关 + 内部服务分层的真实案例
- Astro vs Next.js 静态站选型实践 —— 同一决策框架方法论在前端栈的应用
常见问题
一个项目可以混用 REST、GraphQL 和 gRPC 吗?
可以,而且成熟系统通常就是混合架构:对外开放 API 用 REST(生态兼容性最好),前台 BFF 层用 GraphQL(多端聚合),内部微服务间用 gRPC(性能与强契约)。选型的单位是"接口边界"而不是"整个项目"。
GraphQL 的 N+1 问题怎么解决?
标准解法是 DataLoader 模式:把同一事件循环内的多个单条查询合并成批量查询,配合缓存去重。此外要在网关层加查询深度与复杂度限制,防止恶意或失控的深层嵌套查询把数据库打挂。
gRPC 能直接给浏览器前端用吗?
浏览器不能直接说 gRPC(HTTP/2 帧层控制受限),需要 gRPC-Web 加代理(Envoy 等)转换。所以 gRPC 的主场是服务间调用和移动端/IoT 客户端;纯浏览器前台通常在网关层转成 REST 或 GraphQL。
小团队起步项目直接用 REST 会不会将来后悔?
大概率不会。REST + OpenAPI 是迁移成本最低的起点:文档、测试、网关、监控的生态最全,招人最容易。真正到了多端聚合痛点再引入 GraphQL BFF,到了内部调用性能瓶颈再引入 gRPC——按痛点演进比预先设计更稳。