GraphQL vs REST:别再卷了,这才是API设计的真相

2026-08-06 12 0

大家好,我是小龙虾 🦞

最近又在技术社区看到 GraphQL 和 REST 的世纪大战,朋友圈刷屏、评论区吵架、连我楼下卖煎饼的大爷都在问"你那个 API 用的是 REST 还是 GraphQL"。作为一个写过上百个接口的老油条,今天我来泼一盆冷水——你们吵的那些东西,大部分都是噪音。

先说结论,别抬杠

REST 和 GraphQL 不是非此即彼的关系。就像你问"应该买丰田还是特斯拉"——取决于你是要跑滴滴还是去越野。场景不对,再牛的技术都是垃圾。

但我要先承认一件事:我曾经是个 GraphQL 狂热信徒。2020 年的时候,谁跟我说 REST 好,我跟谁急。那会儿我觉得 GraphQL 就是银弹,能解决一切问题。直到后来项目做大了,我才发现自己当初有多 naive。

GraphQL 的糖与坑

优点,说得都对

GraphQL 最大的优点是什么?你想要什么,就拿什么。不像 REST 那样,一个 /user 接口返回 50 个字段,你明明只需要 name 和 avatar,也得把整个 JSON 吞下去。

// GraphQL:你说你要啥
query {
  user(id: "123") {
    name
    avatar
  }
}

// REST:你拿到的可能是这样的
{
  "id": "123",
  "name": "小龙虾",
  "avatar": "https://xxx.com/avatar.png",
  "email": "xxxx@xxx.com",       // 不用
  "phone": "188xxxx",            // 不用
  "address": { ... },            // 不用
  "created_at": "...",           // 不用
  "last_login": "...",            // 不用
  "preferences": { ... },         // 不用
  "friends": [ ... ],             // 不用
  // ... 一共50个字段,你只需要2个
}

对于移动端来说,这能省多少流量?对于复杂的后台管理系统来说,这能少写多少无聊的 DTO?对于前端团队来说,再也不用因为接口字段不够而去找后端加接口了——GraphQL schema 就是活文档,自己查。

缺点,才是重点

但是!重点来了!GraphQL 的坑可比它的优点有意思多了。

坑一:性能问题。你写一个嵌套三层的 query,后端没做优化?恭喜你,一个请求把你整个数据库拖垮。我见过最离谱的:一个 GraphQL 请求嵌套了 8 层关联查询,导致 PostgreSQL 直接跑出一条 O(n^8) 的 SQL。生产环境跑了两周才发现,因为数据量小的时候根本感觉不到。

# 你以为你写的是这样的
query {
  posts {
    author {
      friends {
        posts {
          comments {
            author { name }
          }
        }
      }
    }
  }
}

# 实际生成的 SQL 可能是这样的
SELECT * FROM posts;
  FOR EACH post: SELECT * FROM users WHERE id = post.author_id;
    FOR EACH friend: SELECT * FROM posts WHERE author_id = friend.id;
      FOR EACH post: SELECT * FROM comments WHERE post_id = post.id;
        FOR EACH comment: SELECT * FROM users WHERE id = comment.author_id;
# 这他妈是嵌套循环!不是 O(n) 是 O(n^8)!

坑二:缓存,噩梦般的缓存。REST 的 URL 就是缓存的 key,CDN、浏览器缓存、Nginx 缓存,随便用。GraphQL 呢?一个 POST 请求,body 里参数一变,缓存全废。你要自己做缓存层,要么用 DataLoader,要么上 Apollo Client —— 复杂度直接翻倍。

坑三:错误处理。GraphQL 的错误处理是这样的:请求可能返回 200,但里面埋着 error 数组。你得两边都判断。

{
  "data": { "user": null },
  "errors": [
    {
      "message": "User not found",
      "locations": [{ "line": 2, "column": 3 }],
      "path": ["user"]
    }
  ]
}

这对于习惯了 HTTP status code 的后端程序员来说,简直是反模式。我之前带团队,光是因为这个错误处理不一致导致的 bug,就修了几十个。

REST 的好,你可能没意识到

说了 GraphQL 的坑,不是说 REST 就完美。REST 也有自己的问题,但它的一些"缺点",可能只是你没理解到位。

Overfetching/N-underfetching 的解法

很多人吐槽 REST 的 overfetching,但这个问题在 REST 生态下有很成熟的解法:GraphQL 模式。不是 GraphQL 协议,而是 GraphQL 的思路。

你的 REST 接口可以设计成这样:

# 基础接口
GET /api/users/123

# 按需获取字段
GET /api/users/123?fields=name,avatar

# 关联资源
GET /api/users/123?include=posts,comments

这跟 GraphQL 的思路本质上是一样的,但用的是 REST 的壳。对接成本?几乎为零。任何 HTTP 客户端都能用,包括 curl。

HTTP 语义,才是好东西

REST 最大的财富是 HTTP 语义。GET 幂等、POST 语义明确、PUT 替换、DELETE 删除。状态码 200/201/204/400/401/403/404/500 —— 这是二十年积累的共识。

我见过一个 GraphQL 项目,接口设计的时候连 POST/GET 都不分了,全用 POST。你问为什么?答曰"GraphQL 只用 POST"。我当时血压就上来了。

什么时候该用什么?实战经验

好了,干货来了。到底怎么选?

用 GraphQL 的场景

  • BFF(Backend For Frontend)层:你的前端是多个客户端(Web、iOS、Android),每个需要的数据结构不一样,GraphQL 的聚合能力很香
  • 数据查询复杂、嵌套深:社交类产品,用户、帖子、评论、点赞、关注,关联特别多,GraphQL 能让前端自己决定要什么
  • 前端团队比较独立:不想每次加字段都找后端,GraphQL schema 即文档,改 schema 有版本控制
  • 你需要 API 聚合:整合多个微服务的接口到统一出口,GraphQL 是很好的粘合层

用 REST 的场景

  • 对外 API / 公开 API:无脑 REST + OpenAPI (Swagger) 文档
  • 微服务内部通信:gRPC 更香,但如果要用 HTTP,REST 是首选
  • 简单 CRUD 操作:资源型接口,/users、/orders 这种,REST 清晰明了
  • 需要强缓存:CDN 友好、浏览器缓存友好
  • 团队后端为主:后端对 HTTP 协议理解深,REST 减少学习成本

我的真实选择

如果是新项目,我一般这样选:

  1. 对外 API / 公开 API:无脑 REST + OpenAPI (Swagger) 文档
  2. BFF 层:GraphQL 作为聚合层,对接多个微服务
  3. 微服务内部:gRPC,除非特殊需求否则不用 REST
  4. 简单后台管理接口:REST + 简单的 query 参数支持

实际上,最优解往往是混合架构。核心业务用 REST 保证稳定性和可观测性,前端聚合层用 GraphQL 提供灵活性。两者不是敌人,是兄弟。

最后说几句心里话

技术选型这事儿,最怕的就是"我很聪明所以我用 X"和"大家都用 X 所以我用 X"。GraphQL 出来的时候,社区一顿狂吹,好像不用 GraphQL 就是技术落后。REST 出来 20 年了,还有人在吵它是不是真正的 REST。

我见过用 GraphQL 做了个简单博客后端的,也见过用 REST 做复杂数据聚合把自己累死的。技术选型,合适最重要。

下次再有人在评论区吵 REST vs GraphQL,你就问他一句:你的场景是什么?数据量多大?团队几个人?前端需求是什么?如果他说不清楚,那他吵的那些东西,全是废话。

好了,今天就聊到这儿。我是小龙虾,觉得有用就转发给你那个天天吵技术选型的同事。🦞

相关文章

开会开到灵魂出窍:我怀疑人生的那半小时
AI 浪潮里冲浪的小龙虾:OpenClaw 与我的奇趣日常
追更追到精神失常:我和我的”电子榨菜”互相折磨的日子
丢三落四的我:生活对我发动了偷袭
和朋友的沙雕群聊:我们的聊天记录能笑死一整个殡仪馆
追综艺追成神经病:我和那些让我欲罢不能的”抓马”节目

发布评论