V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Ayanokouji
V2EX  ›  程序员

GraphQL 有什么优缺点

  •  
  •   Ayanokouji · 2022-03-12 15:37:31 +08:00 · 6851 次点击
    这是一个创建于 768 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如果后端主导使用 GraphQL ,请问使用,还需要避免踩那些坑

    第 1 条附言  ·  2022-03-18 01:12:43 +08:00
    各位不好意思,前几天被限制 720 天不能发言
    现在想问下 2022 年 graphql 的生态怎么样了,比如 java 有 dgs ,写起来也挺方便的
    30 条回复    2023-08-01 18:21:32 +08:00
    pupboss
        1
    pupboss  
       2022-03-12 15:40:12 +08:00   ❤️ 3
    好处主要是可以省流量,省 http 请求次数,坏处其实挺多的,比如鉴权,限流,缓存,性能浪费

    如果你感兴趣的话可以看看这篇:GraphQL 后端架构的经验分享 https://www.pupboss.com/post/2021/experience-sharing-of-graphql-backend/
    bojue
        2
    bojue  
       2022-03-12 15:44:17 +08:00
    @pupboss 现在采用的多不多,我们项目目前遇到的问题是都后端传递字段太臃肿了,每次后端修改字段要等待资源挺麻烦的
    zchlwj
        3
    zchlwj  
       2022-03-12 16:30:45 +08:00
    codehz
        4
    codehz  
       2022-03-12 16:41:11 +08:00 via Android
    缺点:自带自省功能(对于一些实现来说不是那么容易关闭),攻击者可以轻易获取所有 api (
    hooopo
        5
    hooopo  
       2022-03-12 16:41:46 +08:00
    太难了
    pupboss
        6
    pupboss  
       2022-03-12 16:46:01 +08:00
    @bojue 看你的描述好像是说向前兼容的问题,GraphQL 它本质上就是个 API 聚合器,后端该遇到的问题它一个也不会少(我好像还没遇到什么场景下 GraphQL 有碾压型的优势
    auh
        7
    auh  
       2022-03-12 17:05:45 +08:00
    前端如果没有复杂业务。后端用这个,就是浪费。
    micean
        8
    micean  
       2022-03-12 17:15:59 +08:00
    当需要一些关联的数据的时候,比较方便,相当于本来需要人工聚合的部分,框架帮你做了。
    缺点主要是鉴权麻烦,至于安全问题,觉得暂不用考虑。
    XCFOX
        9
    XCFOX  
       2022-03-12 20:00:55 +08:00   ❤️ 6
    正好最近在做的项目前后端深度使用 GraphQL 。

    优点:
    1. 强类型文档。GraphQL 本身首先是一门语言,而且是强类型语言,目前社区已有各种语言与 GraphQL 转换的工具。实践中,前端配合自动生成工具和 TypeScript 能确切知道每个 Query 每个变量每个属性的类型,省去了以往 RESTful API 项目中前端手动声明类型的麻烦。使用如果后端使用 TypeGraphQL 或者 NestJS 这类框架,能直接从 TypeSCript 的 Class 生成文档(schema)。

    2. 自动聚合。以往 RESTful API 的每个接口的数据都是预先设计好的,前端展示的数据和后端返回的数据有时匹配不上,复杂的业务往往需要一层 BFF 层来做数据聚合。GraphQL 的返回数据是由前端决定的,能有效降低前后端的数据耦合程度,并且减少接口调用次数。

    3. 更细致的鉴权。RESTful API 的鉴权颗粒度只停留在路由上,但是 GraphQL 能控制每个字段的访问权限。(讲道理 RESTful 也能,无非实现起来麻烦点)

    缺点:
    1. 迁移成本高。
    2. 生态不完善。如果后端要用 GraphQL 的话目前几乎只能选 Node.js 了。其他语言生态都不完善,缺少 dataloader 、federation 等关键包库。
    其他方面我觉得和 RESTful 相比,GraphQL 简直完胜啊

    坑:
    1. 著名的 N+1 问题。对于后端来说,需要对每一个列表查询进行优化避免 N + 1 。目前流行的解决方案是 dataloader 。
    2. 每个前端项目只能有一张 GraphQL schema 。这使得后端必须部署一个网关来整个各个微服务,目前几乎只能用 Apollo Federation 来解决这个问题。
    3. Subscriptions 。Apollo 实现了 Subscriptions 功能来帮助服务器主动发送消息。但是实践下来发现这个功能还是比较简陋的,不合适微服务架构和集群部署。
    james122333
        10
    james122333  
       2022-03-12 20:28:49 +08:00 via Android
    就是省的多写逻辑重複的 api 然后只是部分回传不同字段 一般 api 前面写个过滤器根据规则过滤一样效果 省流量倒是没有 因为你数据库是一大笔资料取出来 除非架设在一起 然而整理代码也不是不可以
    james122333
        11
    james122333  
       2022-03-12 20:33:53 +08:00 via Android
    好处应该是节省 api 串接沟通成本 但其实整个结构对照并且有测试查寻页面也差不多了
    james122333
        12
    james122333  
       2022-03-12 20:58:12 +08:00 via Android
    这东西其实是大而全的 涵盖不只一个功能
    虽然意义不大但要用也可以 毕竟是方案型
    不爱就是
    masterclock
        13
    masterclock  
       2022-03-12 22:20:28 +08:00
    优点
    一大堆

    缺点
    说法不了:REST/JSONRPC/XXX 就行啊

    @XCFOX 主要语言对 GraphQL 的支持都很好了,
    golang 支持 dataloader ,1.8 后就有泛型 dataloader 可以用了
    golang 也支持 Apollo Federation ,另外还有个库支持 Subscription 的 federation
    Mithril
        14
    Mithril  
       2022-03-12 22:25:19 +08:00
    如果你要对接的 API 消费者,不只是跟你在同一个地点工作的前端同事,他们的需求也不是你们组定的,那么 GraphQL 可以显著减少沟通成本和你自己的开发成本。
    其他情况 RESTful 能遇到的问题,GraphQL 也一样能遇到。并不会省多少事。
    但同样的,RESTful 或者瞎写的接口能做到的,GraphQL 也一样可以做。不止 NodeJS ,其他语言,至少我用过的 C#和 Java 的 Client ,功能也都很全。
    iseki
        15
    iseki  
       2022-03-12 22:50:44 +08:00
    dataloader 也不能解决全部问题,只是粗暴的把 key 聚合起来一次查询而已。整体来看迁移成本太高了,将整个查询控制交给前端,前端给出啥样的查询完全不可控,很容易把后端搞死······
    reeco
        16
    reeco  
       2022-03-12 23:11:37 +08:00 via iPhone
    对后端来说,这玩意除了增加工作量外没有一点好处,想不明白哪个后端会来主导用 graphql
    SjwNo1
        17
    SjwNo1  
       2022-03-12 23:15:47 +08:00
    N+1 问题,其他应该都还好吧。
    ( dataloader 并不能很好地解决这个~)
    pluswu1986
        18
    pluswu1986  
       2022-03-13 00:43:58 +08:00
    @iseki 被搞死。。相当于让客户端写 sql 查询 db 。。反正我们这 go 的 gqlgen 查询一复杂就经常被搞死。。。。
    ericls
        19
    ericls  
       2022-03-13 01:52:12 +08:00 via iPhone
    怎么都比 restful 好
    iseki
        20
    iseki  
       2022-03-13 02:49:00 +08:00 via Android
    传统 API 模式的好处是 API 相对固定,查询模式往往派生自 API ,也相对固定,便于实现和优化; graphql 这种会导致查询模式完全由前端传递,后端进行限制和优化难度陡增。想想是手动实现优化与一个 SQL 等价的查询容易还是编写一个通用的查询优化器容易~ dataloader 相对缓解这个问题,但是彻底解决我看够呛
    Weny
        21
    Weny  
       2022-03-13 02:59:36 +08:00 via iPhone
    相对来说门槛高… 一般来说全栈会倾向选 graphql 。 生态也都很不错,我们在用的 urql,code-generator 可以做到前端包括小程序开发体验都是一致的。我们有一些小项目或者内部的项目,用 graphql 暴露了一套根据 entity 生成的 mongodb query dto 给到前端😂
    twocucao
        22
    twocucao  
       2022-03-13 07:18:28 +08:00
    之前写过一篇文章, 结论大致是 1. 对前端来说很利好. 2. 但对后端来说, 问题蛮多的

    - View 层代码组织剧变
    - 权限问题
    - 版本更迭
    - required vs nullable vs blank
    - 服务端缓存
    - 嵌套式 API
    - N+1 问题
    - 为名所困

    https://zhuanlan.zhihu.com/p/384196319
    loading
        23
    loading  
       2022-03-13 08:15:29 +08:00
    云里雾里,我选择用普通 api 方式。
    ichou
        24
    ichou  
       2022-03-13 09:58:02 +08:00 via iPhone
    优点:
    没人动不动找我改 api 了

    缺点:
    太难了
    特别是 Apollo 引入的复杂度,导致在异常监控、限流、鉴权、缓存方面处理起来贼复杂
    OliveGlaze
        25
    OliveGlaze  
       2022-03-13 10:28:56 +08:00
    @reeco 多少能减少一些沟通成本。我觉得沟通成本也是工作量,不只是你的代码量才是你的工作量。
    ZSeptember
        26
    ZSeptember  
       2022-03-13 12:43:26 +08:00
    @pluswu1986 准备搞 GraphQL ,想问下为什么会有复杂查询问题,Query 应该是后端可以控制提供的吧,可以确保 Query 都走索引,前端只是控制字段扩展什么的吧。
    没有限制的话,不就是把整个 db 都暴露出去了吗
    ZSeptember
        27
    ZSeptember  
       2022-03-13 12:45:49 +08:00
    @XCFOX Apollo 客户端一个项目,只能接一个 endpoint ?后端,准备搞点项目,用 GraphQL ,想的方案是一部分代理到已有的 GraphQL 服务,一部分新写。
    lixm
        28
    lixm  
       2022-03-14 10:55:01 +08:00
    沟通成本,代码生成, 其实完全可以用 openapi 规范来实现
    GraphQL 对后端还是太不友好了
    Ayanokouji
        29
    Ayanokouji  
    OP
       2022-03-18 01:10:27 +08:00
    @ZSeptember graphql 跟数据库无关吧,我理解的,比如 rest 需要查 ID ,name 俩个字段,数据库是 id ,name ,age 三个字段,通常 orm 都是这三个字段都查出来,返回两个,graphql 的逻辑处理应该跟 rest 的一样,只不过 http 的 response 只返回 id 和 name 而已
    pluswu1986
        30
    pluswu1986  
       261 天前
    @ZSeptember 没法控制客户端用各种你想不到的姿势查聚合,而且默认 go graphQL AST 解析就贼慢,普通 HTTP 接口你可以针对特定 URI 做缓存提前聚合最主要时职责清晰谁接口慢就搞谁,不该给客户端的数据就不给,GQL 查询缓存得针对查询级别的然后防不住客户端查询拉不合理的数据,一个查询可能在复杂度超标不超标边缘作死,N 个查询就是大家都不行了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3140 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 14:20 · PVG 22:20 · LAX 07:20 · JFK 10:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.