在使用 restful 中,经常发现无法严格按照 restful 规范来设计,结果就是慢慢的变成的一个仅仅是看起来像是 restful 的设计
因此网上找资料发现了 GraphQL,它可以大量节省请求次数,返回字段由前端决定,也不用写文档了,初步了解之下感觉很不错。
但转念一想可能没这么简单,有没有用过的大佬来说说它有什么坑?
相比 restful 的优劣有哪些?
1
baiyi 2021-01-26 11:31:09 +08:00
graphQL 是给 API 设计的查询语言,应该属于特殊场景(资源有着较多复杂查询)适用。
|
2
jingcoco 2021-01-26 11:50:35 +08:00
我自学了一段时间,前段时间看帖子说热度降了下来,说是前端同学用的爽,但是后端的同学不愿意做. 不过我个人感觉还是想继续学习.然后后端选一个 express 框架的.
|
3
jingcoco 2021-01-26 11:53:53 +08:00
个人没有太懂那个帖子的那个言论,为啥后端这么抵触....
|
4
co1mugx 2021-01-26 11:59:16 +08:00 via Android
调用端是爽了,但是服务端除了写接口还得写描述,不然怎么公布可以获取哪些字段。所以并不能说前端要什么可以自己决定,他要你也得有啊
|
5
EPr2hh6LADQWqRVH 2021-01-26 12:02:15 +08:00 3
Restful 已经是过度宣传实际意义不大的东西了,GraphQL 根本就是这种 xjb 宣传贴大字报行为的无敌威力加强版。
只有一种情况 GraphQL 有用: 当你想把 SQL 数据库查询工作量前置到浏览器的时候。 任何其他情况都不适用, 任何。 如果你的应用是用的 MongoDB 或者任何不是 SQL 的,等着难受吧,恶心死你。 如果你的应用是高度动态的,等着难受吧,恶心死你。 如果你的应用是有分页概念而不是直接查数据库的,等着难受吧,恶心死你。 如果你的应用是你自己设计的有自己的想法会思考,而不是按照丫挺的教程 c-c c-v,等着难受吧,恶心死你 |
6
co1mugx 2021-01-26 12:04:44 +08:00 via Android
之前用 nestjs 的时候但是提供了一个方案,可以通过代码生成 gql 文件,其他框架应该也有类似操作
|
7
atonku 2021-01-26 12:05:01 +08:00
你出任你出,我用算我输。
|
8
adjusted 2021-01-26 12:36:42 +08:00
我们用 graphql schema 生成对应的 go struct,写起来很舒服。GraphQL 初看是一种自定义查询的协议,其实我认为更重要的是类型,代表着 API 开发向 schema driven 和类型的转变,其实挺符合 javascript 向 typescript 转变的倾向。
|
9
FantaMole 2021-01-26 12:38:24 +08:00 5
没有实际业务接口真的会严格按 restful 的标准来执行的,满足不了业务要求。它是一份标准,你可以用来参考,但不是什么都要按这上面来做。而且说句实话,你会发现同一个公司的同事英语水平真是参差不齐,就说 restful 的 api 路径命名,不用动词就要憋死一批人,该不该用复数,又要憋死一批人
|
10
wdhwg001 2021-01-26 12:43:35 +08:00 via iPhone
不看好,因为请求合并了就意味着无法区分主次,服务器端也需要一口气准备所有数据,这样传输的并行还是查询的并行都更难实现。
更不用说,很多时候服务器端是需要对特定的 crud 做优化的,需求放这么开的话这种优化也更困难了。 |
11
zjsxwc 2021-01-26 12:49:45 +08:00
个人觉得 GraphQL 与几十年前的 CS 架构的软件没什么不同,
CS 时代后端直接写数据库存储过程,客户端直接用 SQL,权限控制在 DB 里配置, 历史总是惊人的相似。 |
12
KuroNekoFan 2021-01-26 12:52:09 +08:00 2
如果你有很原子的 restful 后端,graphql 的意义在于减少数据传输的冗余
|
13
mahone3297 2021-01-26 13:04:47 +08:00
|
14
forgottencoast 2021-01-26 13:08:12 +08:00
@FantaMole “该不该用复数” 笑了,真的,只能靠全公司统一规范来解决了。
|
15
bsg1992 2021-01-26 13:14:48 +08:00
GraphQL 和 restful 场景特别特别的小。
|
16
masterclock 2021-01-26 13:30:20 +08:00
个人使用 GraphQL 的主要原因是强类型。
React + TypeScript 下用 introspection 出来的 schema 和 gql tag 里的查询语句预编译生成 react 的 hook,保证编译能过。 服务端用 apollo 的 gateway 做 federation, 组合多个 GraphQL 的后端,几个后端的协调一下命名等,相互间访问和隔离问题都不大。 GraphQL 用来提供 “one api”,跟 SQL 什么的都没什么关系,GraphQL 也不是 SQL 的有效抽象。 用什么数据库也无所谓,反正都在 resolver 里解决。 高度动态确实不太好,直接变成 AnyQL,类型意义全没了。 分页用 Relay 定义,支持 cursor 或 offset,实现起来比较麻烦,但客户端上好用点。 |
17
ReinerShir OP @forgottencoast 想问下查询参数很多的情况下你们是怎么解决的? restful 规定查询使用 get,参数拼 url 后面,但是参数一多,那个参数栏惨不忍睹,取值、维护都很麻烦,所以我们是直接查询用 POST 、参数放 BODY 里
|
18
coolair 2021-01-26 13:32:50 +08:00
权限不好控制
|
19
676529483 2021-01-26 13:47:17 +08:00
如果你的接口需要门框模式(也就是经常需要把几个接口整合起来,减少调用次数),GraphQL 很赞。当然这是前端,后端不会减少代码量
|
20
bruceshi 2021-01-26 13:50:41 +08:00
1. GraphQL,代码生成是必不可少的,不论是 code first 还是 schema first,要不然会很麻烦,选择一个好的工具(框架)很重要,有兴趣的同学可以看下[NestJs]( https://docs.nestjs.com/graphql)的一些实现
2. GraphQL 是 API 查询语言不等于 GraphQL 直接查询数据库 3. GraphQL 只是一种新的组织 API 查询方式和结构的工具,本质上还是 HTTP 4. 说 MongoDB 的,我觉得不论是 Restful 还是 GraphQL 我都会死,GraphQL 和你用什么 DB 没有本质上的关系 5. GraphQL 也可以很简单的分页,如果觉得分页有问题的,我相信是看到网上很多使用 [Relay]( https://relay.dev/docs/en/graphql-server-specification.html#connections) 提到的分页方式,代码在自己手里,想写简单就写简单点。 6. 权限控制的话,可以精确到 field level,不知道大家提到的权限问题具体是什么,我暂时没遇到很复杂的权限控制,没有什么发言权。 7. 复杂度,可以通过定义 complexity 控制。 8. 缓存问题,payload 大的问题,GraphQL 可以通过[persisted queries]( https://www.apollographql.com/docs/apollo-server/performance/apq/)将 POST 变成 GET 9. 多学习,多思考,而不是无脑黑一个夸一个。再黑的东西也有闪光点。 |
21
wwwap 2021-01-26 13:59:22 +08:00
debug 挺麻烦的, 开发者工具里全是 /api/graphql 的请求,只有点开看 request 和 response 才能搞清谁是谁。
|
22
dk7952638 2021-01-26 14:06:06 +08:00
graphql 爽不爽主要看两点,
一是调用端愿不愿意接受,虽然很简单,体验很好,但是总有一群人,学习个新东西比杀了他们还难, 第二是后端实现一个完整的 graphql 服务其实复杂度很高,做缓存也比较难,对后端团队的技术要求很高,错误的实现方式反而会让问题更复杂, 另外还有一点,graphql 的生态比较完善的是 node,而国情目前还是 java 天下, 综上所述,这东西在已经有自己的技术栈或者权力比较分散的大公司比较难推,小公司小团队可以试试 |
23
linoder 2021-01-26 14:11:57 +08:00
graphql 适合企业级后台 别的场景真不适合 ……
|
24
KIMMG 2021-01-26 15:04:39 +08:00
我从 restful 过渡到了 graphQL 。
这里说说感受,restful 实际上是一种约束,它约束 API 设计应该遵循资源规范。用户资源和订单资源是分开的。 但这种设计是方便后端的,按照这种设计,由于业务的组合,前端需要多次发起调用不同资源的 api,就很繁琐了。 实际业务中很难严格遵守这种规范,导致 /users/{id}/orders/{id} 这种情况经常出现。 甚至 /users/getUser 这种完全不是 restful 风格的 api 的出现。 而 graphQL 的结构声明,其实也是 restful 思维的扩展。 现实是,api 的设计过于随意,graphQL 中结构的声明也很少遵从设计原则。依旧是导致资源嵌套很深。 到头来写的二不像。 |
26
xuanbg 2021-01-26 15:44:40 +08:00 6
graphQL 没有解决任何问题,反而增加了系统的复杂度。前端发明的东西经常如此。
|
27
keepeye 2021-01-26 15:48:50 +08:00
只要对整体有利,那就值得,不能光考虑前端调用方便而忽视后端的难度增加
|
28
janxin 2021-01-26 16:13:22 +08:00
GraphQL 和图的关系了解一下,所以可以建模为图关系的都可以用
不过问题是由于耦合很大,所以会导致优化起来难度远比 Restful 方案更麻烦 |
29
nigelvon 2021-01-26 16:19:46 +08:00 2
用了 3 年多了,现在内部项目全部上 GraphQL,版本迭代速度快了很多。接口性能也有大幅上升。底层微服务提供粒度很小的 API,方便做缓存,中间层用 GraphQL 组装数据,前端按需调用,爽得飞起。
|
31
ReinerShir OP @nigelvon 我明白了,你的架构是低层服务访问数据库,api 走 restful,非常分散的那种,中间层做业务逻辑,负责接收前端请求然后调用低层服务,但是这样其实还是多次调用,只不过中间层把它封闭了而已,不知道我理解得对不对。
|
32
uselessVisitor 2021-01-26 16:42:46 +08:00
要前端参与业务设计,相当于后端一个大接口,到 GraphQL 按需选取数据
|
33
jsq2627 2021-01-26 17:22:10 +08:00
近 1 年都在和 GraphQL 打交道,接触的方面包括:
1. 前端 apollo client 和后端 node.js apollo server 打交道,后端是重业务代码 2. 前端 apollo client 和后端 graphql ruby 打交道,后端也是重业务代码 3. 前端 react query 和后端 node.js apollo server 打交道,后端是 BFF 层 总结一下个人对 GraphQL 评价 优点: - schema-driven 的开发流程,衍生出一系列好处:代码生成、精确的接口文档。类比 RESTful 的 swagger 。 - 很容易实现 field 粒度的 ACL - 良好的类型系统,对 normalization 、cache 、codegen 等都非常友好 - 有官方 spec,不像 RESTful 有各种不同的解读方式(尽管 spec 没有提到分页,但 relay style 已经成为了事实标准) 缺点: - 各类 HTTP debug 工具支持都很弱 - 大规模 scale out 的实践比较少,缺少成熟的基础设施( gateway,细粒度监控,日志,限流,等等) - 很难利用 HTTP cache,需要前端自己实现 cache 系统 - 服务端 n+1 查询问题 - 和 RESTful 一样,只是一种工具,没有官方范式。有人会写嵌套很深的 field,有人会像 RESTful 一样全部扁平化,甚至有人写出来是 RPC style (我见过 root query 顶层 field 全部是 `getXxxByXxx` 的命名风格) - 使用最广泛的 apollo-client 至今稳定性欠佳,bug 很多 |
34
jsq2627 2021-01-26 17:31:00 +08:00
有个印象很深刻的项目,充分使用 apollo-client 的 cache 后,前端状态管理变的非常简单(一般业务项目,所谓前端状态管理,基本就是把 fetch 回来的数据存到 store 里面; apollo 的 cache 已经帮你全搞定了)。
这个项目最后只用了 React 原生 hooks / useReducer / context 做状态管理,以及一小部分 apollo local state 。 |
35
forgottencoast 2021-01-26 17:32:54 +08:00
@ReinerShir
你是说的前端吗?反正后端是不会手工拼参数的。 对于后端来说,如果需要大概都会使用类似 AddParameter(A, a)的方法来手动添加参数。 因为对于 HTTP 规范来说,参数的形式都是一样的: A=a&B=b&C=c GET 和 POST 的区别在于放在 header 还是 body 。 |
36
IvanLi127 2021-01-26 18:57:24 +08:00 via Android
很好用,前后端都能省很多事,就是后端这边,关联查询的性能好像不是很好优化。
|
37
xuanbg 2021-01-26 20:58:59 +08:00
@Desiree 这个还需要用过才知道吗?前端需要的数据是和页面匹配的,一个页面一个特定的接口获取数据难道不是最简单也是最合适的做法吗?这个数据的内容和形式,由前端决定还是前后端协商决定,这个数据难道会有丝毫的不同吗?
|
38
leeg810312 2021-01-26 23:06:02 +08:00 via Android
graphql 是客户端驱动开发,我的理解是他的目的是为了最小化客户端向后端请求,小项目可能比较容易做,大型项目对系统交互设计要求很高,而且要有很强的后端团队才能用好,否则系统性能和运维会有很大问题
|
39
masterclock 2021-01-26 23:11:10 +08:00
@Desiree 一个页面一个特定的接口?
对前端来说肯定是最美好的世界,但后端怎么办?一个页面很多都会包含来自多个模块、服务、系统的数据,后端怎么办?前端增减页面、页面中的数据,后端一起改? 由前端决定还是前后端协商决定,这个数据确实会不同啊,前端肯定想着一个 API 拿到所有格式化好的数据,后端肯定想拿到砍人啊 |
40
wwk 2021-01-26 23:18:15 +08:00
增加了复杂度,并且目前缺乏好的工具链来搭配使用。
|
41
aliipay 2021-01-27 00:32:26 +08:00
@forgottencoast 规范这些纯属浪费时间 ,工作量不饱和才搞这些玩意
|
42
forgottencoast 2021-01-27 00:59:07 +08:00 1
@aliipay 夏虫不可语冰
|
43
coymail 2021-01-27 01:13:00 +08:00 via iPhone 1
GraphQL 更适合 OLAP 场景,拿来干 OLTP 不太合适,是个类似 Gremlin 的图查询结构
|
44
Sparetire 2021-01-27 01:32:10 +08:00 via Android
看明白了,这帖子里挺多用都没用过就开始口嗨的
|
45
wobuhuicode 2021-01-27 09:24:04 +08:00
GraphQL 个人项目做起来爽。前后端都是自己控制的,查询语句放到前端去一点问题都没有。但是放在团队来说的话,减轻了后端压力,但是增加了前端工作量。同时增加了沟通成本。
restful 陈旧?但是规范。而且基本上所有后端都有自己一套 apidoc 方案。写完代码写上注释就出文档。 |
46
fansfans 2021-01-27 10:18:59 +08:00
@ReinerShir 我觉得这种情况下用 post 问题也不大 比如前端出现多选搜索的情况 这个时候需要传递一个列表 同时内容比较多容易超出浏览器限制 用 post 是最稳妥的。
|
47
flyhelan 2021-01-27 10:29:00 +08:00
@wobuhuicode
怎么你这里说是减轻了后端压力?前面的朋友说的是增加了后端的压力。 |
48
a67793581 2021-01-27 10:55:16 +08:00
@flyhelan 技术好的减轻工作量 技术不好的增加工作量 因为这个东西资料不多工具也少 很多时候要考验后端的技术能力
|
49
ReinerShir OP |
50
WinnieNumberTwo 2021-01-27 15:20:11 +08:00
@flyhelan 后端压力主要在于学习新的技术,真正掌握了的话最终增加的是前端的业务压力:)
|
51
630071099 2021-04-14 16:49:06 +08:00
准备使用,被 CTO 驳回了,是前微软老开发,说微软都不用……
|
52
chengdonghui 2021-05-06 16:59:28 +08:00
1 降低接口开发的代码量 配合可实现 graphql 自动化的编程框架,比如 hasura 可自动生成 graphql 接口服务,其他编程语言和框架也有类似的
2 增强了接口的灵活性,也可以适应前端的需求变更 比如前端要求加个字段或者返回关联对象的时候,不用增加接口或者重写接口了,前端组织 ql 语句就能实现了 |
53
obwj 2022-06-17 09:40:25 +08:00
graphql 3 年老用户在此,已生产使用无数次,应用到不同产品,深爱 graphql
|
54
tangkikodo 325 天前
https://github.com/allmonday/pydantic-resolve 可以试试, 用 RESTful + 申明式的类型描述来生成组合数据。
|