基于 GraphQL 实践的一点思考

hello~亲爱的观众老爷们你们好~最近一直沉迷于 GraphQL 的应用实践,正好公司黑客马拉松临近,就拉上了两位小伙伴,结合实际的业务场景,把 GraphQL 做为中间层的解决方案提上去~项目完成度还算不错,对 GraphQL 也有了更深刻的理解,在此记下整个过程的收获。前端

注意~这篇文章不是学习 GraphQL 语法的文章,语法学习可左转传送门。但如若你对 GraphQL 有必定的了解,想知道实践中可能碰到什么问题,那估计本文能给你带来一点帮助~如下是正文:程序员

业务中的困局

既然要用 GraphQL,那仍是要先了解它究竟是什么:数据库

GraphQL 既是一种用于 API 的查询语言也是一个知足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端可以准确地得到它须要的数据,并且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。后端

看起来没什么复杂的地方,也许你看过 GraphQL 的相关介绍,会认为它的语法很繁杂(这我却是不否定),但归根到底,它就是为了查询而生。本质上就是丢一段东西给服务器,服务器解读这段东西后,把对应的数据丢回来给你而已,全部的语法都为此而服务。缓存

简单介绍完 GraphQL,也要简单介绍一下业务的背景~咱们组真正的后端服务是用 C++ 进行编写的,有一层很薄的 Go 做为网关与中间层,负责沟通页端与 C++ 后端,同时提供解密、鉴权 等基础服务。但因为业务的瓶颈不在前端(也致使话语权比较小),致使 C++ 后端常常表现得不那么“业务”,也不认为为前端提供服务是工做的关键之一。致使他们对于不少后端能作与应该作的事情视而不见。后端隐含的态度基本是:“又不是不能用~”。但这对前端的代码质量与研发效率形成了负面的影响。服务器

站在前端的角度,如今的系统存在如下问题:网络

  • 接口冗余,影响页端性能;
  • 数据体不规范,不一样接口相同的 value,key 可能不一致;
  • 接口文档维护困难,文档中 key 的大小写、value 的类型常常不一致,修改字段后文档也存在滞后性;
  • 没法提供 Mock 服务。

因为各类缘由,推进后端改变比较困难,那就本身从新架一套吧。新的中间层,使用 TypeScript 开发,选用了 Egg.js 为框架,魔改了 egg-graphql 这个插件做为 GraphQL 服务的基础。提供实时规范的接口文档、0 配置 Mock 服务、动态配置且热更新等功能。框架

如下是功能与使用先后区别的一些截图:运维

接口文档:工具

配置后台:

页端使用 GraphQL 以前:

页端使用 GraphQL 以后:

(除了合并请求以外,不妨心算一下响应体大小区别)

新服务带来的变化

相信你们对 GraphQL 的优势已了然于胸,经过上文对新的中间层的描述,也能感觉到 GraphQL 的优势。这里就不凑字数去详述节省的带宽、性能的提升及其它为前端带来的其余便利。这里主要想讨论一下的是,归根到底,咱们是但愿解放生产力,那么 GraphQL 解放了什么?

咱们认为:GraphQL 能减小先后端矛盾,让彼此更专一自身!

尽管上文吐槽了一把后端同窗,但换个角度上,他们的作法无可厚非。接口单1、专一是合理的设计,冗余的接口是由于版本与多端须要,Mock 服务更是后端无关的。不管前端仍是后端,都是站在本身的立场去思考业务,并根据自身的技术为业务提供解决方案。可是业务是一个总体,程序员却被分为了先后端。两端中间的灰色区域,尽管能提升某一端的研发能力,但对另外一端而言,倒是至关麻烦的。那么:

All problems in computer science can be solved by another level of indirection.

既然灰色区域难于处理,那就再抽象一层!GraphQL 应运而生~它整合与提供了大量的功能,其中包括但不限于:文档服务、Mock 服务、单一入口、去冗余、数据聚合等功能。解决了先后端的矛盾,后端可专一于自身,提供稳定而健壮的服务,再也不关心前端 UI 所需数据及其意义;前端专一于页面与交互,按需获取对应数据,接口稳定、文档清晰。

我的认为,GraphQL 根本的优势是:让各端更专一自身,更有效地解耦彼此。

阳光下的阴影

既然有光,那么确定会有影子,如下是劝退使用 GraphQL 的时间(笑)。因为我是一个至关怕麻烦又容易放弃的人,每当我碰到表现比现存系统更差或实现起来至关麻烦的时候,就会不自觉地思考新的技术是否适用于当前场景。如下是实践过程的一些思考(已经明确的缺点:如缓存、n+1 的问题等在此再也不详述):

中间层使用 GraphQL 多是一个伪命题

GraphQL 很好,它清晰的标识了每一个字段的类型与含义,以此为基础扩展出文档服务、Mock 服务、去冗余等功能。但成也萧何败萧何,做为中间层,通常是比较轻薄的,通常只是校验与动态转发内容便可,然而 GraphQL 其实至关重的。这致使了后端改字段的时候,不单后端要发版,中间层也须要发版。为解决这个问题,咱们千方百计对 GraphQL 服务进行动态配置及热更新,尽管实现了这一功能,但里面使用的都是 JavaScript 的黑魔法,如何迁移到其余语言(如 Go,公司在 Go 语言运用上已经比较成熟),说实话,我真不知道。而对于合并请求优化性能而言,GraphQL 也不是惟一的解决方案,Http2 同样能解决问题~

BFF 中尴尬的处境

若是不将 GraphQL 做为中间层转发的技术,而做为 BFF(Backend For Frontend)中请求的主要查询语言,则会碰到一个比较尴尬的场景。在 BFF 中,前端掌握了服务器,那么接口的质量其实前端是能把握的。此时 GraphQL 只是一种选择,它并无解决太多的问题,但它的学习与接入成本又不低。多少有点高不成低不就的感受。

接入成本的评估

此处的接入成本,不单指编写 GraphQL 相关代码的成本,还包括如何接入到公司现行系统的成本。因为 GraphQL 获取数据的方式,存在瞬间请求大量数据的可能,很容易拖垮数据库,然而请求的人却对此一无所知。这有点像当初邮件系统刚出的时候,用户往邮件中扔视频文件同样,尽管是无心的行为,却对系统形成极大的伤害。同时,谁去接也是一个值得商榷的问题。说到底,这是“爽”前端的技术,后端同窗对此兴趣乏乏。然而接入须要相关的开发与运维能力,前端同窗不必定有足够的能力去接,毕竟不是每一位同窗都是全栈。其余的问题还有 rpc 接入、权限控制等等。在方案落地以前,这些都须要仔细进行评估,不能盲目“追新”。

小结

综上所述,GraphQL 能够为咱们带来不少便利,但它的接成本并不低。我的认为,GraphQL 并非从根本上解决某个问题,而是在先后端之间几个龌龊的地方进行了改进。在考虑是否使用 GraphQL 以前应进行多方面的考量。它比较适合如下的场景:

  1. 技术包袱比较小且业务不断迭代。
  2. 业务接口十分复杂或多版本兼容的场景(如报表系统、基础的万用接口等)。
  3. 接口细碎,但又对网络十分敏感的场景。

最后感谢 @Scott 相关的指导,尽管你给的建议每一条都用了其余方式去实现(笑)~但无疑是开阔了咱们的眼界。

以上是我的的一点浅见,感谢各位看官大人看到这里。知易行难,但愿本文对你有所帮助~谢谢!

相关文章
相关标签/搜索