一句话定义:GraphQL 是一种 API 查询语言兼运行时。客户端用一段结构化文本写明“我要哪些字段”,服务端照单返回,而不是由后端预先定好一个个固定接口。
打个比方:套餐窗口 vs 点菜
REST 像食堂的套餐窗口——每个窗口(endpoint)只给你一整盘固定搭配。你只想要盘子里的土豆,它也会把整盘端给你。
GraphQL 像自助点菜:通常只有一个入口(常是 /graphql),你写一张订单,指明要哪几道菜、每道菜要哪几样配料。
```graphql
query {
user(id: 42) {
name
posts(last: 3) { title }
}
}
```
一次请求就拿到“用户名 + 他最近三篇文章标题”这个嵌套结构。而在 REST 下,你要么请求两次,要么让后端专门加一个定制接口。
能这么干的前提是服务端有一份 schema(类型系统 schema),它声明“有哪些对象、哪些字段、字段什么类型、能怎么组合”。订单先被 schema 校验,再由每个字段对应的 resolver 函数去取数。
和 REST 的关键区别
| 维度 | REST | GraphQL |
|---|---|---|
| 端点 | 一资源一端点 | 通常单一端点 |
| 返回字段 | 服务端定 | 客户端定 |
| 多次取数 | 多次请求或定制接口 | 一次请求嵌套获取 |
| 版本演进 | 常靠 /v2 这类新路径 | 靠新增字段 + 废弃(deprecation)标记 |
| HTTP 缓存 | URL 即 key,天然好做 | URL 相同,得另想办法 |
| 限流 | 按请求数算 | 一个请求可能触发大量后端调用 |
代价一:缓存变难
HTTP 缓存和 CDN 靠 URL 当 key。GraphQL 的请求通常都是 POST /graphql,URL 一样、body 不同,CDN 分不清谁是谁。常见解法是客户端归一化缓存,或者把查询持久化:查询文本先登记成一个 ID,实际请求只发 ID 和参数,走 GET,这样又能被 URL 缓存覆盖。
代价二:限流变难
REST 里“一秒 100 个请求”就是 100 次后端调用。GraphQL 里一个请求可能展开成上千次数据库查询,甚至被深层嵌套或循环引用打爆。所以要限制查询深度、估算查询复杂度(cost)、设超时、做查询白名单。还有个常见坑是 N+1:resolver 逐字段取数,得靠批处理(如 DataLoader 思路)合并。
另外,GraphQL 习惯“HTTP 200 + errors 数组”,状态码语义和 REST 不同,监控也得按 operation name 归类而不是按 URL。
对从业者和普通人的意义
对前端和移动端:少等后端排期加接口,弱网下少传无用字段,省流量也更快。对后端:schema 就是一份可执行的契约,前后端能并行开发,但复杂度控制和监控必须提前设计。顺带一句,这份带类型的 schema 对语言模型相当友好,常被当作“可被 Agent 调用的工具清单”来用。
对普通职场人:看到接口文档里只有一个端点,别以为它只有一个功能——能力全在 schema 里。反过来说,简单的 CRUD 小项目、重度依赖 CDN 的静态内容,用 REST 往往更省事:GraphQL 不是升级,是换一种取舍。具体实现细节以官方文档为准。
