- 后端
- 文档
- 教程
【免费下载链接】system-design-101
Explain complex systems using visuals and simple terms. Help you prepare for system design interviews.
本篇技术指南以仓库文档 data/guides/rest-api-vs-graphql.md 为核心,系统拆解 REST 与 GraphQL 两种主流 API 风格的设计理念、核心机制与适用场景。无论你是正在设计新服务的后端工程师,还是需要为团队选择统一接口方案的架构师,读完后你将掌握两者的取舍逻辑,能够基于"前端需求的变动频率、数据关联的复杂度、缓存与安全的诉求"做出可论证的选型决策。
为什么 REST 和 GraphQL 常被放在一起比较
在 API 设计中,REST 与 GraphQL 是两种最具代表性的风格:REST 以"资源 + 标准 HTTP 方法"为哲学,把接口拆成一组简单、统一、可预测的端点;GraphQL 则以"图 + 客户端声明式查询"为哲学,用一个端点让客户端精确描述想要的数据形状。两者各有所长,也各有所短——选择的关键从来不是"谁更好",而是"谁更适合你的应用场景与团队结构"。仓库中另一篇 SOAP vs REST vs GraphQL vs RPC 从更长的时间线上对比了四种风格,而本文聚焦 REST 与 GraphQL 这两大主流。
REST:简单、统一的接口契约
核心机制:标准 HTTP 方法与 CRUD 映射
REST(Representational State Transfer)的核心约束之一是使用标准 HTTP 方法直接对应资源的增删改查操作:
| HTTP 方法 | 用途 | 典型语义 |
|---|---|---|
| GET | 读取资源 | 幂等、安全,可被缓存 |
| POST | 创建资源 | 非幂等,通常不可缓存 |
| PUT | 整体更新资源 | 幂等 |
| DELETE | 删除资源 | 幂等 |
这种"方法即动词、URL 即名词"的约定让接口具备极高的可预测性:客户端只要知道资源路径,就能推断出可执行的操作与大致的行为特征。仓库中的 REST API Cheatsheet 进一步强调了 REST 设计的六大基本原则(如客户端-服务器、无状态、可缓存、统一接口等),以及 HTTP 方法、协议、版本化、分页、过滤等落地要素;How does REST API work? 则从原则、方法、约束与最佳实践四个角度给出了概览。
优势:统一契约与直白的缓存
原文档明确指出 REST 的两大核心优势:
- 适用于需要简单、统一接口的场景:当接口用于分离的服务与应用之间的通信时,REST 的资源化模型几乎不需要额外约定,天然适合作为系统间的稳定契约。
- 缓存策略实现直接:REST 直接复用 HTTP 语义层的缓存机制。通过
Cache-Control、ETag、Last-Modified等响应头,配合 CDN 与反向代理,就能按 URL 对 GET 响应做缓存,无需引入额外的缓存组件。这类"以 URL 为缓存键"的模型简单且被生态广泛支持。
短板:多轮往返组装关联数据
REST 的代价在于:当客户端需要的数据分散在多个资源上时,往往要发起多次请求才能拼装出完整视图。例如查询"某个用户的订单及其商品明细",客户端可能需要依次请求/users/{id}、/users/{id}/orders、/orders/{id}/items,每次往返都叠加网络延迟,且存在返回过多无关字段(over-fetching)的可能。原文档对此的概括是:它可能需要多次往返(multiple roundtrips)才能从不同端点组装出关联数据。这种"客户端自行拼接"的模式,正是 GraphQL 试图解决的痛点。
GraphQL:单端点上的精确查询
核心机制:类型系统、Query、Mutation、Subscription
GraphQL 是一种面向 API 的查询语言,也是一套依托类型系统执行查询的运行时。根据仓库文档 What is GraphQL?,它由 Meta 于 2012 年内部研发、2015 年公开发布。GraphQL 服务器位于客户端与后端服务之间,可以把多个 REST 请求聚合成一次查询,并把资源组织成一张"图"。
原文档总结了 GraphQL 的三大操作类型:
- Query(查询):客户端按需读取数据。客户端在嵌套查询中精确声明所需字段,服务器只返回包含这些字段的优化载荷(optimized payloads),不多不少。
- Mutation(变更):用于修改数据,弥补查询只读的限制。
- Subscription(订阅):用于接收关于 Schema 变更的实时通知,适合推送类场景。
一个典型的 GraphQL 查询与 REST 的对比:
query { user(id: "u123") { name orders { id items { title price } } } }同样的数据视图若用 REST 实现,通常需要多次请求并自行裁剪字段。这正是原文档所说"客户端指定嵌套查询中的确切字段,服务器返回仅含这些字段的优化载荷"的具体体现。
优势:精确取数、多源聚合、适应快速变化的前端
原文档给出了 GraphQL 的核心优势:
- 单端点精确取数:所有查询走同一个端点,客户端声明式描述数据需求,天然避免过度/不足获取(over/under-fetching)。
- 聚合多数据源:GraphQL 服务器可以在后端聚合多个服务的数据,一个查询即可拿到分散在不同服务里的信息。
- 适配快速演进的前端需求:前端字段需求变动时,只需调整查询语句,无需后端新增端点、版本升级或联调,这在多端(Web/移动端)团队并行迭代时尤为高效。
仓库中的 What is GraphQL? 还补充了更多收益:数据获取更高效、返回结果更精准、强类型系统管理实体结构可减少错误、适合管理复杂微服务。
代价:客户端复杂度、滥用查询与缓存难题
原文档同样明确列出了 GraphQL 需要警惕的三点:
- 复杂度转移(shifts complexity to the client):精确取数的自由意味着客户端要理解 Schema、编写并维护查询,查询的可观测性和调试成本会高于"端点即文档"的 REST。
- 滥用查询风险(abusive queries):客户端可以请求任意深度的嵌套数据,如果没有防护,一次深度嵌套查询就可能拖垮服务器。常见的防护手段包括查询深度限制、复杂度评分/配额、超时控制以及持久化查询(persisted queries)白名单。
- 缓存更复杂:REST 按 URL 天然缓存,而 GraphQL 所有请求共用单端点,URL 无法作为缓存键。通常需要引入基于字段级别的缓存方案(如各类客户端缓存库),或者依赖服务器端数据加载器(Data Loader 这类批处理与缓存机制)来缓解重复查询。
REST vs GraphQL 核心差异对照表
| 维度 | REST | GraphQL |
|---|---|---|
| 端点模型 | 多个资源端点(如/users/:id) | 单一端点,按查询取数 |
| 数据获取 | 端点返回固定结构,易过度/不足获取 | 客户端精确声明字段,载荷优化 |
| 关联数据组装 | 多次往返(roundtrips)自行拼装 | 嵌套查询一次完成 |
| 操作模型 | GET/POST/PUT/DELETE 映射 CRUD | Query / Mutation / Subscription |
| 缓存 | 复用 HTTP 缓存,策略直接 | 缓存键设计复杂,需额外方案 |
| 复杂度归属 | 后端负责固定契约,客户端简单 | 客户端负责声明查询,复杂度前移 |
| 多源聚合 | 需网关或服务端编排 | 天然适合聚合多服务数据 |
| 典型风险 | 端点膨胀、关联数据往返多 | 滥用查询、深度嵌套拖垮服务 |
选型决策指南
原文档给出的结论是:最佳选择取决于应用与团队的具体需求。可落地的判断标准如下:
- 前端需求复杂、迭代频繁:移动端/多端展示形态各异,字段组合随版本频繁变化——GraphQL 的按需查询能避免"为所有端设计一劳永逸的端点",是更合适的选择。
- 需要聚合多个数据源:一个页面要拼装来自多个后端服务的数据——GraphQL 服务器作为中间层聚合,能显著减少客户端请求数。
- 偏好简单、一致的契约:系统间接口稳定、语义固定、需要明确的服务间边界——REST 的简单统一更占优,契约变更成本低,团队心智负担小。
- 缓存是第一优先级:对读多写少、流量峰谷明显的场景,REST 复用 HTTP 缓存的低成本优势很难被替代。
仓库中的 GraphQL Adoption Patterns 为"决定引入 GraphQL 后怎么落地"提供了四种模式:客户端侧 GraphQL(客户端包裹现有 API)、BFF(Backend-for-Frontends,为每个客户端建立专属中间层)、单体 GraphQL(多团队共享一个 Schema/代码库)、以及 GraphQL Federation(多个子图合并为超级图,由联邦网关路由请求)。其中 Federation 把数据所有权保留给领域团队,同时避免重复建设,是大型组织的常见演进方向。
关于"单端点是否一定需要网关",《How GraphQL Works at LinkedIn》(data/guides/how-does-graphql-work-in-the-real-world.md) 提供了一个真实世界的反例:LinkedIn 通过查询注册表(query registry)管理客户端查询、借助随查询附带的路由元数据在流量路由层将请求分发到正确的服务集群、并在服务运行时缓存已注册查询——刻意不部署 GraphQL 网关,原因是避免额外的一跳网络延迟、并消除单点故障。这说明:即便采用 GraphQL,是否引入网关层也取决于对延迟和可用性的权衡,而非固定答案。
从本仓库延伸阅读
本仓库围绕 API 设计提供了成体系的配套资料,建议按需深入:
- What is GraphQL?:GraphQL 的定义、收益与局限详解;
- How does REST API work?:REST 原则、方法与约束概览;
- REST API Cheatsheet:REST 六大原则与分页、过滤等实操要素;
- SOAP vs REST vs GraphQL vs RPC:四种 API 风格的时间线与横向对比;
- A Cheatsheet on Comparing API Architectural Styles:SOAP/REST/GraphQL/gRPC/WebSocket/Webhook 六风格速查;
- GraphQL Adoption Patterns:四种 GraphQL 落地模式;
- How GraphQL Works at LinkedIn:不设网关的 GraphQL 生产实践;
- Top 5 Common Ways to Improve API Performance:分页、缓存、压缩等 API 性能优化手段(对 REST 缓存策略尤其有参考价值)。
总结:REST 与 GraphQL 不是零和博弈,而是同一问题空间里两种不同的取舍。简单、稳定、跨系统契约与低成本缓存优先选 REST;数据关联复杂、前端多变、需要多源聚合时,GraphQL 的精确取数与单端点模型能显著提升开发效率——但请务必为查询深度与复杂度设防,并为缓存设计好替代方案。
- 后端
- 文档
- 教程
【免费下载链接】system-design-101
Explain complex systems using visuals and simple terms. Help you prepare for system design interviews.
相关推荐
Umi-OCR 免费离线 OCR 工具完整指南:截图、批量图片与 PDF 识别一步到位
Umi OCR 免费离线 OCR 工具完整指南:截图、批量图片与 PDF 识别一步到位 你是否遇到过这样的情况:手里是一份扫描版 PDF,能看到字却复制不出;或
OCR桌面应用System Design 101 速查:六种主流 API 架构风格对比(SOAP / REST / GraphQL / gRPC / WebSocket / Webhook)
System Design 101 速查:六种主流 API 架构风格对比(SOAP / REST / GraphQL / gRPC / WebSocket /
后端文档教程docker-alpine-java镜像全解析:JDK、JRE与DCEVM版本如何选择?
docker alpine java镜像全解析:JDK、JRE与DCEVM版本如何选择? docker alpine java是一个基于AlpineLinux构
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考