site logo

Marico's space

2026 年 REST、GraphQL 与 gRPC:架构师决策矩阵

前端技术 2026-07-22 14:49:21 7

最近在给团队做技术选型,三种 API 风格吵得不可开交。REST 派说成熟稳定,GraphQL 派说灵活高效,gRPC 派说性能碾压——各有各的道理,但放在一起比就是鸡同鸭讲。

这篇把三个协议各自的最佳场景说清楚,结论很简单:没有银弹,但有明确的适用边界。

🔗 这篇文章有一个可交互版本,可以通过点击选择你的边界场景(公开 API、内部服务调用、移动端/带宽受限),直接看结论——还有一张对比 REST、GraphQL、gRPC 往返次数的图:点此查看

TL;DR

  • 公开 API? 用 REST。可缓存、可调试,调用方已经会了,不用教。
  • 内部服务间调用? 用 gRPC。契约、Streaming、Protobuf 序列化比 JSON 快约 3 倍——性能和类型安全都赢了。但别用在公开 API 上:浏览器原生不支持 gRPC,外部调用方需要 grpc-web 加翻译代理,光这个基础设施就够第三方喝一壶的。
  • 一个后端服务多个前端? 用 GraphQL——但前提是你得像做产品一样维护 Schema。
  • 协议选择本质上是组织决策,不是技术偏好。按边界选,不要按公司选。

问题背景

想象一个中型物流平台,有司机 App、调度员 Web 控制台、40 多个内部服务,还有供第三方仓库集成的合作伙伴 API。团队想把三代 API 风格统一成一套标准,结果每个派系都觉得自己那套最好。最容易犯的错误——也是大多数团队会犯的错误——是选一个"万能方案"。没有这种事。API 有三个边界,每个边界有各自的正确答案。

按边界选协议

交互版本可以逐个点击查看场景。下面是同样的内容。

公开 API → REST

你的合作伙伴那边可能是个只会 curl 的初级开发,他脑子里想的是微信支付 API 那种风格——REST 在这里赢在零学习成本,HTTP 原生支持 CDN 缓存(ETag、Cache-Control 这些都是现成的),加上 20 年的工具链沉淀:网关、限流器、OpenAPI 代码生成、Postman。版本管理也是早就解决了的无聊问题。

注意:别因为"灵活性"就冲动把 GraphQL 暴露给公网。对着你的数据库写复杂查询的能力,开放给匿名用户,这不是开玩笑的事:微信支付和支付宝的公开 GraphQL API 都是按查询成本做限流的——不是简单数请求次数,而是根据查询涉及的表和关联提前算出复杂度,Shopify 更是把每个字段、每个连接都折算成点数。这才是公开 GraphQL 的代价:你实际上是在 JSON 请求计数器的基础上,又搭了一套计费引擎。

内部服务间调用 → gRPC

在自家服务器上跑,两端都是你的人,不用考虑人类能不能读懂协议内容,把精力全花在契约和效率上。Protobuf Schema 提供编译时就能检测出的跨团队类型问题,各语言都有生成的客户端,双向 Streaming 对某些场景(进度更新、事件流)处理起来也比 REST 优雅得多。

gRPC 官方发布的移动端基准测试比营销文案说的更细致,也更可信:Protobuf 序列化速度比 JSON 快约 3 倍,跟消息大小无关;但反序列化取决于 payload 大小——1KB 以下的小消息 JSON 其实比 Protobuf 快约 1.5 倍,只有超过 15KB 时 Protobuf 才拉开约 2 倍的差距。如果对 JSON 启用 Gzip 压缩,Protobuf 序列化优势扩大到 5 倍以上,反序列化在小消息时差不多持平,大消息时 Protobuf 快约 3 倍。HTTP/2 多路复用和 HPACK 头部压缩进一步拉开差距,消息越大、并发越高差距越明显。

注意:调试体验会下降。从第一天起就得配上 grpcurl、服务反射、还有拦截器级别的日志——"我在代理日志里看不了明文 payload"是上线半年后的团队第一大抱怨。另外"内部"的意思是服务对服务调用。浏览器打不开原生 gRPC 连接,需要 grpc-web 加一个转成 HTTP/2 的代理,这是实实在在的额外基础设施,不是随便提一句就能忽略的。

移动端 / 带宽受限场景 → GraphQL

这是 GraphQL 真正发挥价值的地方:一个界面需要用户信息、该用户的发货单、每张发货单的最新状态,网络还是信号不稳的蜂窝网。在我那个演示用的 POC 仓库里(不是正经 benchmark,见下方说明),这种情况用 1 次请求、33% 的 REST 流量就搞定了。在 300ms 往返延迟的连接上,把 5 次请求合并成 1 次,用户感知到的延迟能省出一秒多。

注意:N+1 问题不会消失,只是转移——从客户端的多次请求转移到你的 Resolver 端。如果字段解析写得糙,每条记录都会重新触发一次查询,除非你做了批处理(DataLoader 等方案)。而且一旦匿名或半可信的客户端能自定义查询,一个嵌套很深的查询可能发散成海量的数据库调用。微信支付和支付宝不对外开放 GraphQL 公网接口也是这个原因——他们按查询涉及的表和关联计算复杂度,在执行前就定价。

如果不愿意做(或者买)这套成本核算和 Resolver 批处理机制,就别上线通用 GraphQL。用几个针对具体页面优化的 REST "端点"(BFF 模式)能达到 80% 的收益,只用 20% 的运维成本。

权衡矩阵

REST GraphQL gRPC
Payload 大小 / 效率 返回完整资源,容易过度获取;嵌套数据需要 N+1 次请求 精确获取字段,一次请求——但线路上跑的仍是 JSON 文本 Protobuf 二进制格式——序列化比 JSON 快约 3 倍,不限消息大小;反序列化在小消息(1KB 以下)JSON 快约 1.5 倍,大消息(15KB 以上)Protobuf 快约 2 倍;原生支持 Streaming
工具链 / 调试体验 curl、浏览器、任意代理——所有工具都认识它 自省和 GraphiQL 很优秀;但错误藏在 200 OK 里 二进制不透明;需要 grpcurl、反射、protoc 工具链
缓存支持 原生支持:ETag、CDN、浏览器缓存——都是现成的 全用 POST 请求导致 HTTP 缓存失效;需要持久化查询加客户端规范化 基本靠自己实现——但内部服务调用很少需要共享缓存
调用方学习成本 接近零——互联网的事实标准 真金白银的学习曲线:查询语言、Fragment、错误语义、客户端库 生成的客户端像本地函数调用一样自然;但 proto 和构建配置对外部调用方是个门槛

(表中"优势"和"代价"都是相对比较——每个格子都是真实的权衡,不是白捡的好处。)

数据说话,不凭感觉

我写了个纯 Python 标准库的 POC(链接在下方),模拟一个具体请求——"获取一个用户、该用户的 3 篇文章、每篇文章的 2 条评论"——分别用三种风格实现。这是一个简化的演示,不是正经 benchmark:只测了一种 payload 形态,没有压缩、没有真实网络、没有模拟服务端处理成本。百分比数字反映的是机制原理,不是行业统计数字。

Protocol Round-trips ~Bytes vs REST
REST 5 3,105 100%
GraphQL 1 1,017 33%
gRPC 1 629 20%

是的,开启 Gzip 会缩小 JSON 的字节差距。但 Gzip 解决不了多出来的 4 次往返——在移动端,往返次数才是决定性因素。

gRPC 官方基准测试的结论比"二进制永远赢"这种话术更细致——正因为如此才值得引用。Protobuf 序列化速度比 JSON 快约 3 倍,跟消息大小无关。反序列化跟大小有关:1KB 以下的小消息 JSON 反而比 Protobuf 快约 1.5 倍,只有超过 15KB 时 Protobuf 才明显领先约 2 倍。对 JSON 开启 Gzip 压缩,Protobuf 序列化优势扩大到 5 倍以上,反序列化在小消息时基本持平,大消息时 Protobuf 快约 3 倍。结论:对于微小型 payload 和内部轻量 RPC,朴素 JSON 反序列化完全够用,甚至更快——gRPC 的优势随着消息体积和并发规模增长而增强,这跟上面那个玩具 POC 的方向是一致的。

经验法则:外部陌生人调用你,用 REST。自己内部服务互相调用,用 gRPC。多个界面调用同一个后端,用 GraphQL——而且你得像维护产品一样维护 Schema。

我的真实立场

观察这些技术选型几年下来的结果,规律很明显:大多数公开 API 不需要 GraphQL,而很多上了 GraphQL 的团队正在默默交维护税——成本限制器、持久化查询、Resolver 性能排查——这些麻烦 REST 根本没有。同时 gRPC 在内部服务间的使用严重不足:团队宁愿手写 JSON 客户端调用自己的服务,说"REST 更简单",然后每季度花一周时间排查契约漂移问题——这些问题一个 .proto 文件在编译时就能发现。

高级的做法不是选最花哨的方案,而是把协议匹配到信任边界,然后这一季不再重提这个话题。

往返次数和字节数对比的 POC 在这里。公网 benchmark 数据单独引用。有不同意见?正常——告诉我哪个格子不对,为什么。

参考与延伸阅读

  • gRPC 官方博客——"Mobile Benchmarks"
  • Shopify Engineering——"Rate Limiting GraphQL APIs by Calculating Query Complexity"