- 原文地址:GRAPHQL: A RETROSPECTIVE
- 原文做者:Rob Kirberich
- 译文出自:掘金翻译计划
- 本文永久连接:github.com/xitu/gold-m…
- 译者:EmilyQiRabbit
- 校对者:Eternaldeath
在 2016 年底,咱们决定用 Python 和 React 重写老旧的 PHP 遗留系统。因为只有四个月的时间在 2017 年的节日(到来前)及时创建 MVP(模式开发的系统),咱们必须很是谨慎地决定如何投入时间。前端
咱们投入使用的技术之一就是 GraphQL。咱们中以前还历来没有人用过它,但咱们认为它对于快速交付以及能让人们独立工做相当重要。python
事实证实这是一个很是好的决定,因此两年后咱们想回顾并分享从那时起学到的东西...react
咱们从遗留系统学到的教训,大大影响了咱们,因而咱们决定使用 GraphQL。咱们在至关数量的微服务之间使用 REST APIS,致使不少混乱,如不兼容的接口,不一样的资源标识符和很是复杂的部署。任何 API 的变更都须要同时部署全部使用了这个 API 的服务以免停机故障,这会常常出现错误并致使很长的发布周期。在单个 API 网关使用 GraphQL,咱们将能够大大简化服务格局。咱们也决定了使用 Relay,它为咱们提供了一种识别资源的单一的、全局的方式,以及组织 GraphQL 模型的简单方法。android
咱们使用单一服务做为 GraphQL 服务器,它反过来会请求各类后端服务 -- 其中大部分是 REST APIs,可是由于它们都只和网关通讯,因此它们可使用任何想用的接口。网关被设计为彻底无状态的,这对于可扩展性大有裨益。缓存也是在 GraphQL 网关中,所以,只需扩大网关实例的数量,就能够轻松扩展整个系统。ios
API 网关并非 GraphQL 世界的规章,因此为何尽管使用它们意味着须要从网关到后台服务的附加请求,咱们还要使用呢?对于咱们而言,最大的缘由就是减小 API 的相互依赖。没有网关的话,咱们的服务结构将会差很少像这样:git
不少服务都和不少其余服务互通,致使须要大量的 API 链接,链接数量会以大体至关于服务数量的二次方的速度增加。这不但几乎不可能让任何人记住,同时还在处理中断,维护和 API 更改时,增长了大量复杂性。github
即便在这样的网络中,GraphQL 也可以帮助提高向后兼容性,但这是当你在服务之间放置一个单一网关的时候所会发生的事情:web
突然间,就仅有线性数量的链接了,每一个新的服务仅会在网络图中增长一个新链接。API 变化仅须要影响它的源服务和网关。数据库
API 网关是服务互相通讯的惟一途径,这就大大下降了复杂度。它还为缓存,缩放,监视和分析建立了一个很好的中心位置。通常来讲,只有一项服务负责这么多事情并非一个好主意 -- 而是一个故障点。django
可是,API 网关是无状态的。它没有数据库,没有本地资源也没有认证。这意味着它能够在水平方向上缩放自如,同时由于它还负责了缓存,因此仅增长网关实例的数量就有助于显著解决流量高峰(的问题)。
固然,网关也不是全无代价的:一个请求如今要发送两次了,而且若是一个后台服务想要和另外一个后台服务通讯,就必须经过网关。这对于建立一个更易于维护的中心接口很是有用,可是对于性能来讲并非很好。这就是无状态网关展示本身光辉的时候。由于网关代码在哪里运行并不重要,那就没有什么能阻止咱们将每一个后端服务都做为其本身的网关。咱们将 GraphQL 接口移动到了每一个服务中,直接发送网络请求,而不是发送两次,这样彻底不须要使用 GraphQL 服务器,可是却依旧保留了全部 GraphQL 中心模型的优点。而且因为咱们使用了 Python 定义了 GraphQL 模型,咱们决定更深一步,经过从 GraphQL 模型中自动生成 API 包装器,能够直接在 Python 中使用它。
结果就是如今服务间的通讯代码变成了以下这样:
GraphQL 模型的 API 包裹器是彻底从 graphene schema 自动生成的。因此,服务甚至不须要模型文件的副本。没有多余的请求,身份验证在后台透明处理,字段在访问时会被延迟解析。
如今,在这样的环境中,成为一个好的 API “公民”就会有一些要求了。后台 API 大多能够作任何它们想作的事情,可是在如何进行缓存和权限检查的时候它们必须发挥很好的做用。咱们在后端 APIs 中使用的规则以下:
在 REST API 中返回嵌套的对象是减小请求数量的一个很好的方法。可是这也让缓存很是困难,并可能致使获取多余的资源,这正是 GraphQL 应该对抗的。一般状况下,咱们避免大的,复杂的请求,而更偏向于稍多可是容易缓存的,更加扁平化的请求。
有时候性能要求超过了简单性的要求,那咱们就能够返回潜逃的对象,例如,在一个 API 应答中包含一个相关联的嵌套对象的长列表。可是,咱们只在被嵌套对象的权限不比外层对象更严格的状况下这样作,由于若是不这样,应答就没法被缓存。
咱们使用 graphene 和 graphene-django 来实际运行服务器,咱们不使用 graphene-django 自动映射 Django 模型的能力,由于全部的数据都来自外部请求,咱们只使用它来与咱们的堆栈的其他部分兼容并熟悉它。整个网关服务实际上就是一个单独的 GraphQLView,咱们作了一点小小的扩充来容许咱们对前端作出优化:
GraphQL 对咱们大有益处,可是咱们也犯了不少错误。有时候咱们会努力保持咱们的 API 能真正向后兼容,除了性能监控和更好的错误报告,还必须为已弃用的字段投入额外的监控。每次 API 变化就须要手动更新 GraphQL 模型,这是至关乏味的事情;而且为了经过 GraphQL 使后台服务的通讯变得很是容易,咱们有时也会打破一些服务的边界。但最终,它帮助咱们更快地发展,维持了基础设施核心模型的简易,并使咱们的团队更加自动化。
若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。