REST
核心思想:把一切看作资源,用 HTTP 方法表示操作。
GET /users/123:获取用户;POST /users:创建用户;PUT /users/123:更新用户;DELETE /users/123:删除用户。
约束:无状态、统一接口、可缓存、分层系统。
优点:
- 简单直观,学习成本低;
- 可以利用 HTTP 的缓存机制(CDN、浏览器缓存);
- 生态成熟,工具丰富;
- 易于调试(用 curl 就能测试)。
常见问题:
一、过度获取(Over-fetching):客户端只需要用户名的列表,接口却返回了完整的用户对象。
二、获取不足(Under-fetching):要展示一个页面,需要调用多个接口(用户信息、订单列表、推荐商品……),产生"N+1 请求"问题。
三、版本管理:接口演进时,/v1、/v2 的版本管理可能变得繁琐。
GraphQL
由 Facebook 在 2015 年开源。
核心思想:客户端声明自己需要哪些数据,服务端按声明返回。
query {
user(id: "123") {
name
orders(limit: 5) {
id
total
}
}
}服务端只返回 name 和 orders 中指定的字段。
优点:
- 按需获取:解决了过度获取问题;
- 一次请求聚合多个资源:解决了获取不足问题;
- 强类型 Schema:前后端有明确的契约,工具链(代码生成、自动补全、文档)支持好;
- 前端可以自主调整所需数据,减少后端改接口的往返。
代价:
一、缓存更复杂。 所有请求都走 POST /graphql(同一个 URL + 不同的 body),HTTP 层的缓存机制难以直接使用。需要客户端侧的缓存方案(如 Apollo Client 的规范化缓存)。
二、查询复杂度不可控。 客户端可以构造极其复杂的嵌套查询,可能压垮服务端。
应对:查询深度限制、复杂度分析、分页限制、持久化查询(只允许预定义的查询)。
三、学习曲线。 需要理解 Schema、类型系统、解析器(Resolver)、DataLoader 等概念。
四、错误处理。 GraphQL 通常返回 200 状态码,错误信息在响应体的 errors 字段里——这与 HTTP 语义的集成需要额外设计。
怎么选
适合 REST:
- 简单、稳定的资源型 API;
- 需要充分利用 HTTP 缓存;
- 团队对 REST 更熟悉;
- 对外开放 API(客户端多样,REST 的通用性更好)。
适合 GraphQL:
- 客户端需求多变(如多个前端平台,各自需要不同的数据形状);
- 数据关系复杂,一个页面需要聚合多个来源;
- 前端团队希望减少与后端的接口往返协调;
- 有 BFF(Backend for Frontend)层的需求。
一个务实观察
GraphQL 并不是 REST 的"升级版",而是一种权衡不同的选择。
它把复杂度从"多次请求协调"转移到了"服务端查询优化和复杂度控制"。
很多团队在引入 GraphQL 后发现,真正的难点不在 API 层,而在数据聚合层的性能(如何高效地从多个数据源取数,避免 N+1 查询——这正是 DataLoader 要解决的问题)。
说明:本文为 API 设计的知识整理。