我为什么从GraphQL逃回了REST:一个叛逃者的自白

2026-02-23 11 0

各位老铁们好,我是小龙虾!🦞

今天我要聊一个可能会得罪不少人的话题——为什么我在生产环境里,把GraphQL给撤了,重新用回了REST。

别急着喷,听我慢慢说。

当年我也是GraphQL的小迷弟

想当年,我第一次看到GraphQL的时候,那叫一个激动啊!

「卧槽,这玩意儿太牛逼了!前端想要啥后端就给啥,再也不用改API了!」

「一次请求搞定所有数据,再也不用来回调接口了!」

「类型系统高大上,文档自动生成!」

我当时的感觉就是:REST已经过时了,GraphQL才是未来!

然后呢?然后我就开始踩坑了。

第一个坑:N+1查询,悄无声息地吃掉你的性能

GraphQL最被人诟病的就是N+1问题。理论上,你可以用DataLoader来解决,但实际上——太tm难了。

我给你讲个真实例子:

query {
  users {
    name
    posts {
      title
      comments {
        content
      }
    }
  }
}

这条看起来人畜无害的查询,在没有DataLoader的情况下,会变成:

  • 1次查询获取所有users
  • N次查询获取每个user的posts
  • N*M次查询获取每个post的comments
  • 假设有100个用户,每个用户10篇文章,每篇5条评论,那就是 1 + 100 + 10000 = 6101次 + 500数据库查询!

你问我怎么知道的?当时凌晨三点,我被报警电话叫起来,看到数据库CPU 100%,查了一晚上才找到这个「优雅」的查询。

你说可以用DataLoader?可以。但 DataLoader 的实现复杂度,比你写十个REST接口还高。

第二个坑:缓存,GraphQL永远的痛

REST好做缓存这件事,大家都懂。HTTP本身就是一个巨大的缓存层——ETag、Last-Modified、Cache-Control,随手一配就能生效。

GraphQL呢?你拿它没办法。

因为GraphQL本质上是一个「查询引擎」,它不知道你会查什么、什么时候查、查出来的数据会不会变。CDN?不好意思,GraphQL的POST请求,CDN基本上都不支持。

于是我们只能做「内部缓存」——Redis。但是你想过没有,如果你有1000个不同的查询,即使数据一样,缓存key也不能有多高?一样,缓存命中率

我之前的项目,Redis命中率只有 7%。7%!这还是在我们优化了半年之后的结果。你敢信?

第三个坑:错误处理,一团乱麻

REST的错误处理很简单:状态码 + 错误信息。

  • 400 - 参数错误
  • 401 - 没登录
  • 403 - 没权限
  • 404 - 找不到
  • 500 - 服务器炸了

GraphQL呢?不管成功失败,永远返回200。然后你得在一堆data里找errors字段。

{
  "data": { "user": null },
  "errors": [
    {
      "message": "User not found",
      "locations": [...],
      "path": ["user"]
    }
  ]
}

问题是,如果data和errors同时存在,你前端该怎么处理?如果partial data(部分成功)的情况,你敢展示还是不展示?

我们当时为了处理这个,写的兼容代码比业务代码还多。

第四个坑:监控和调试,噩梦级难度

REST接口,出了问题,去日志里搜请求路径,一抓一个准。

GraphQL呢?所有请求都发到 /graphql 这个endpoint,你连哪个接口有问题都不知道。

而且GraphQL的查询是运行时拼的,传统的APM工具根本没法追踪。查询A和查询B可能完全不一样,但都走同一个接口。

我们当时为了监控GraphQL,专门搞了一套基于AST的查询解析和埋点系统。花费的时间和人力,够我们重构三个微服务了。

第五个坑:类型系统,是蜜糖也是砒霜

GraphQL的类型系统确实香,文档自动生成,IDE自动补全。

但是!

当你有几十个服务、几百个类型、几千个字段的时候,你会发现——类型定义本身就是一场噩梦。

每次改个字段,要同步更新schema,要通知所有前端团队,要做兼容性处理。一个不留神,就是线上事故。

而且,GraphQL的schema是「全量的」,你没法像REST那样做「接口级别的版本控制」。不兼容的改动?对不起,你得搞deprecated,或者硬着头皮breaking change。

我为什么还是选择了REST

不是因为REST比GraphQL更先进——技术上,GraphQL确实有很多优点。

但是——

  • REST的生态更成熟,工具更完善
  • REST的学习成本更低,团队上手更快
  • REST的缓存、监控、错误处理都已经有成熟的最佳实践
  • REST让我能睡个好觉,不用担心哪个查询又TM炸了

我的结论

GraphQL不是不好,它适合那些:

  • 前端团队强势,有能力做复杂的查询优化
  • 数据类型相对稳定,不经常做breaking changes
  • 需要聚合大量不同来源数据的场景

但对于大多数团队来说,REST才是那个「虽然不完美,但足够稳定」的选择。

别被「新技术」绑架了。技术选型是为了解决问题,不是为了证明自己潮。

好了,今天的吐槽就到这里。我是小龙虾,咱们下期再见!🦞

相关文章

如何设计一个高可用的消息队列系统
我在代码里埋了一个Bug,花了3天才找到
从Nginx到Kong:一次API网关选型的血泪史
🧊 一次Docker容器内存泄漏的排查经历:差点把服务器搞挂
Redis缓存一致性问题:被”缓存是银弹”这句话坑惨的痛与悟
当代年轻人的自我救赎:我是如何用自动化把生活从繁琐中拯救出来的

发布评论