978 字
5 分钟
GraphQL vs REST:下一代 API 架构的终极对决与迁移指南

引言:API 调用的“自助餐”革命#

在传统的 RESTful 架构中,前端开发者就像在餐厅点菜:

  • 我要一份用户信息 (GET /users/1)
  • 我要一份该用户的文章列表 (GET /users/1/posts)
  • 我要每篇文章的前 3 条评论 (GET /posts/{id}/comments?limit=3…)

这就像服务员跑了三趟腿,端上来一大桌子菜。有时候你只想要个“用户头像”,结果接口硬塞给你整个 User 对象(包含手机号、邮箱、注册时间等敏感信息)。

这就引出了 REST 的两大原罪:

  1. Under-fetching (获取不足):需要发 N 个请求才能凑齐一个页面所需的数据。导致 RTT (Round Trip Time) 爆炸。
  2. Over-fetching (获取过多):带宽浪费,前端解析耗时。

GraphQL 的出现,就是为了把“点菜”变成“自助餐”。 “我要:用户的头像、前 5 篇文章的标题和第一条评论。” —— 只发一个请求,不多不少,精准送达。


一、GraphQL 的核心概念#

GraphQL 不是 SQL,它是一种 查询语言 (Query Language),也是一个运行在服务端的 运行时 (Runtime)

1.1 Schema (契约)#

一切始于类型定义 (Type System)。

type User {
id: ID!
name: String!
avatar: String
posts(limit: Int): [Post]
}
type Post {
id: ID!
title: String!
comments: [Comment]
}

1.2 Query (查询)#

前端拥有绝对的控制权:

query {
user(id: "123") {
name
posts(limit: 5) {
title
# 甚至可以嵌套查询评论
comments {
content
}
}
}
}

二、后端实现的挑战:Resolvers 与 N+1 问题#

天下没有免费的午餐。GraphQL 把前端的复杂度转移到了后端。

2.1 Resolver (解析器)#

每个字段都需要一个函数来获取数据:

const resolvers = {
User: {
posts: (parent, args) => {
return db.posts.findAll({ where: { userId: parent.id } });
}
}
};

2.2 臭名昭著的 N+1 问题#

如果你请求一个用户列表,并请求每个用户的文章:

  1. 查询用户列表:SELECT * FROM users LIMIT 10 (1次)
  2. 对每个用户,Resolver 都会被调用一次:SELECT * FROM posts WHERE user_id = ? (10次)

总共 11 次数据库查询。如果是嵌套列表,这个数字会指数级增长。

解决方案:DataLoader

Facebook 提出了 DataLoader 模式。它利用 JavaScript 的 process.nextTick (Event Loop),将这一轮循环中的所有 ID 收集起来,合并成一个 SQL:

SELECT * FROM posts WHERE user_id IN (1, 2, 3, ..., 10)

这样就把 N+1 变成了 1+1。


三、GraphQL vs REST:全方位对比#

维度RESTGraphQL
数据获取多端点,固定结构单端点,按需获取
缓存利用 HTTP 缓存 (ETag),极其成熟只有一个 POST,HTTP 缓存失效,需客户端缓存 (Apollo)
版本控制/v1/, /v2/无版本 (Deprecation 字段级废弃)
错误处理HTTP 状态码 (404, 500)永远 200 OK,错误在 JSON body errors 字段
开发体验需维护 Swagger 文档强类型,文档自动生成 (GraphiQL),前端有代码提示
安全性简单需防范深层嵌套攻击 (Query Depth Limit)

四、什么时候该用 GraphQL?#

不要为了赶时髦而切 GraphQL。

适合场景:#

  1. 多端应用:Web、iOS、Android 需要不同字段。REST 很难兼顾,GraphQL 一套 Schema 搞定。
  2. 复杂关联数据:社交网络、电商详情页(商品+评论+推荐+优惠券)。
  3. BFF (Backend for Frontend):微服务聚合层。GraphQL 非常适合作为网关,聚合底层几十个微服务的数据。

不适合场景:#

  1. 简单 CRUD:杀鸡焉用牛刀。
  2. 文件上传:GraphQL 处理二进制流比较麻烦(虽然有 Multipart 规范,但不如 REST 直观)。
  3. 分析/报表:大数据量的导出。

总结#

GraphQL 是 API 发展的必然方向,它代表了 强类型声明式数据获取 的胜利。 但它也带来了基础设施的复杂性(网关、缓存、监控)。

作为全栈开发者,我的建议是:对外开放的 API (OpenAPI) 依然保留 REST,对内的高交互前端应用,全面拥抱 GraphQL。

GraphQL vs REST:下一代 API 架构的终极对决与迁移指南
https://www.oferry.com/posts/a56/
作者
晨平安
发布于
2026-02-09
许可协议
CC BY-NC-SA 4.0
封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00