GraphQL 技术栈揭秘

本文整理自2017年 GraphQL 峰会上的演讲,详述缓存、追踪、模式拼接和 GraphQL 将来发展等有关话题。

Facebook 开源 GraphQL 至今已两年有余。两年来,社区成倍增加,成千上万的公司在产品中使用 GraphQL。在今年10月份举办的 GraphQL 峰会上,我有幸在次日发表开幕主题演讲。读者能够在 YouTube 上观看完整的演讲,或阅读本文浏览概要。html

首先,我将介绍一下 GraphQL 的现状,而后讨论在不久的未来如何发扬它的主要优点。具体来讲,咱们将介绍三个完整的 GraphQL 集成示例:缓存,性能追踪和模式拼接。让咱们开始吧!前端


GraphQL 的特别之处?

有三个主要因素使得 GraphQL 从其余 API 技术中脱颖而出:java

  1. GraphQL 拥有明确的查询语言,这是描述数据需求的好方法,还有定义良好的模式,可以暴露 API 能力。它是惟一可以指定方程两侧(译者注:视图和模型)的主流技术,它的全部优点都源于这两个概念的相互做用。
  2. GraphQL 可以帮你将 API 提供者与消费者解耦。在像 REST 这样基于端点的 API 中,返回数据的结构由服务器决定。在 GraphQL 中,响应的结构与使用它的 UI 代码保持关联,这样会更加天然,使得你能够专一于关注业务而不是技术
  3. 因为 GraphQL 查询会被附加到使用它的代码上,所以能够将该查询视为数据获取单元。GraphQL 可以预先知道 UI 组件的全部数据需求,从而启用新的服务器功能。例如,在单个查询中对底层 API 调用进行批处理和缓存,表明了 UI 中某一部分所需的数据,使用 GraphQL 将会令其很是简单。

关注业务,而不是技术:GraphQL 将数据需求放在它们所属的客户端。git

如今,咱们来看看人们对于数据请求常常关注的三个方面,以及 GraphQL 如何利用上面提到的属性进行全方位改进。github

请注意,虽然下面讨论的许多功能是你如今就可以使用的,但其中一部分仍属于将来的愿景。若是你和我同样对这件事感到兴奋,那么请滚动到底部参与其中。数据库

1. 交叉请求缓存

人们常常问的第一件事情就是——我怎么用个人 GraphQL API 作交叉请求缓存?将常规 HTTP 缓存应用于 GraphQL 时会出现这样一些问题:后端

  • HTTP 缓存一般不支持 POST 请求或长缓存键
  • 越复杂的请求可能意味着更少的缓存命中
  • GraphQL 的传输是独立的,所以 HTTP 缓存并不老是可行

可是,GraphQL 也带来了许多新的可能性:缓存

  • 访问后端时,在模式和解析器旁声明缓存控制信息的可能性
  • 基于模式的自动化细粒度缓存控制,而没必要单独考虑每一个请求

咱们应该如何使用 GraphQL 来生效缓存,以及如何利用好这些新的可能性呢?ruby

究竟应该在哪里执行缓存?

首先,咱们得肯定缓存功能应该设计在哪。一开始的直觉多是缓存逻辑应该放在 GraphQL 服务器自己内。然而,像 DataLoader 这样简单的工具在同时执行多个 GraphQL 请求时并不能很好地工做,而将缓存功能放在咱们的服务器代码中会使实现变得很是复杂。所以咱们应该把它放在别的地方。服务器

事实证实,就像在 REST 中同样,在 API 层的两端都进行缓存是有意义的:

  1. 在位于基础设施层中的 GraphQL API 以外缓存整个响应。
  2. 缓存 GraphQL 服务器底层对数据库和微服务的请求。

对于第二点,须要你现有的缓存基础设施工做良好。对于第一点,咱们须要一个位于 API 以外的层,而且可以以 GraphQL 的方式执行缓存等操做。本质上讲,这种架构可以将复杂度从 GraphQL 服务器中分离出来:

将复杂度转移到位于客户端和服务器之间新的分层。

我将这个组件称之为 GraphQL 网关。在 Apollo 团队内部,咱们认为这个新的网关层很是重要,每一个人都须要将其做为 GraphQL 基础架构的一部分。

这就是为何在今年的 GraphQL 峰会期间,咱们推出了首个 GraphQL 网关 Apollo Engine

用于缓存控制的 GraphQL 响应扩展

正如我在开始时提到的那样,GraphQL 的一大优势是其拥有巨大的工具生态系统,全部工具都围绕着 GraphQL 的查询和模式来工做。我认为像缓存这样的功能也应该以一样的方式工做。这就是为何咱们要介绍 Apollo 缓存控制,它使用了 GraphQL 规范中内置的一个名为 扩展 的特性,将缓存控制信息包含在响应中。

使用咱们的 JavaScript 参考实现,能够很容易在你的 schema 中添加缓存控制标识:

使用 apollo-cache-control-js 的缓存控制标识

这个新的缓存控制规范创建在 GraphQL 的主要优点上,我对此感到很是兴奋。它使你可以细粒度地指定相关数据的信息,并利用 GraphQL 执行将相关的缓存控制标识发回给调用者,并且这与语言和传输方式无关。

自从我在 GraphQL Summit 上发表这个演讲后,Oleg Ilyenko 已经发布了 Sangria 的缓存控制工做版本,由他维护的 Scala GraphQL 实现。

使用网关缓存

如今咱们能够在 GraphQL 服务器中返回缓存控制标识,因此咱们有一个明确的方法来在网关中进行缓存。技术栈中的每一部分都起着做用:

技术栈中全部部分之间的协做能够借助缓存来完成。

须要注意的一件很酷的事情是,大多数人已经在他们的 GraphQL 栈中拥有了一个缓存:好比 Apollo Client 和 Relay 这样的库在前端缓存你的数据。在 Apollo 客户端的将来版本中,来自响应的缓存控制信息将被用于自动在前端过时旧数据。因此,就像 GraphQL 的其余部分同样,服务器描述它的功能,客户端指定它的数据需求,而后一切工做配合正常。

如今,咱们来看看另外一个贯穿整个技术栈的 GraphQL 功能的例子。

2. 追踪

借助 GraphQL,前端开发人员可以以相较基于端点的系统更精细的方式处理数据。他们能够确切地请求他们须要的数据,并跳过他们不打算使用的字段。受益于此,咱们能够展现详细的性能信息,并之前所未有的方式使其具备可操做性。

不要知足于不透明的总查询时间—— GraphQL 使你可以获晓字段级别的详细耗时。

你能够认为 GraphQL 是首个内置细粒度查看的 API 技术。这不是借助某个特定的工具—— GraphQL 第一次合理地让前端开发人员可以得到逐个字段的执行时间,而后调整他们的查询来解决问题。

跨栈追踪

事实证实,追踪跟缓存同样,对于整个栈的协做大有裨益。

每一部分在提供追踪数据和使其具备可操做性方面发挥着做用。

服务器可以提供相关信息做为响应结果的一部分,就像提供缓存标识同样,网关能够提取和聚合这些信息。重申,使用网关组件来处理复杂的功能,而不是在服务器进程中处理。

在这种状况下,客户端的主要功能是将查询与 UI 组件链接起来。这很是关键,所以你能够将 API 层的性能与其对前端的影响联系起来。这将是首次,你能够直接将后端请求的性能与其在页面上受影响的 UI 组件关联起来。

GraphQL 追踪扩展

就像缓存同样,经过利用 GraphQL 的响应扩展功能,可以以服务器无关的方式实现上述功能。Apollo Tracing 规范已经在 NodeRubyScalaJavaElixir 上实现了,其定义了一种 GraphQL 服务器以标准方式为解析器返回耗时数据的方式,可以被任何工具所使用。

想象一下,你全部的 GraphQL 工具均可以访问性能数据:

共享抽象容许工具使用诸如追踪数据等信息。

借助 Apollo Tracing,你能够在 GraphiQL,编辑器或其余任何地方获取性能数据。

目前为止,咱们一直在谈论单个客户端和单个服务器之间的交互。咱们的最后一个例子,一块儿来看看咱们如何经过 GraphQL 来模块化咱们的架构。

3. 模式拼接

GraphQL 最好的地方就是能够在一个地方访问全部的数据。可是,这样作的代价是:你须要将整个 GraphQL 模式做为单个代码库来实现,以便可以在一个请求中查询它。 若是你拥有一个模块化的架构,而该架构同时具备单个统一 GraphQL API 的好处呢?

模式拼接的概念很简单:GraphQL 能够很容易地将多个 API 合并为一个,所以你能够将模式的不一样部分实现为独立的服务。这些服务能够分开部署,用不一样的语言编写,甚至能够由不一样的组织维护。

这有一个例子

在单个查询中结合来自 GraphQL 峰会的票务系统和天气 API 的数据:
https://launchpad.graphql.com/130rr3r49

在上面的截图中,你能够看到对于一个拼接 API 的单个查询是如何将提供不一样服务的两个独立查询合并在一块儿,这种方式对客户端来讲是彻底不可见的。经过这种方式,你能够像使用乐高积木般合并多个 GraphQL 模式。

咱们实现了一个能用的版本,放到了 Apollo graphql-tools 库里,你能够如今去试用。具体查看文档。

在网关中拼接

模式拼接的概念在整个栈中也能够很好地工做。咱们认为新的网关层长期来看会是一个执行拼接操做的好地方,你可使用任何你想要的技术构建你的模式,如 Node.jsGraphcoolNeo4j

事实证实,模式拼接与 GraphQL 栈的每一部分都息息相关。

客户端也能够加入进来!就像你使用一个查询从多个后端加载数据同样,你也能够在客户端上组合数据源。最近发布的 Apollo Client 2.0 中的新客户端状态管理功能使你能够在单个查询中获取来自于客户端状态和任意数量后端的数据。

结论

但愿你经过阅读这篇文章或者看完演讲后能知道一件事情,那就是尽管现今的 GraphQL 工具已经很棒了,将来还有更多的潜力。咱们只是抓住了 GraphQL 提供的抽象和功能的表面。

我想以上述提到的概念的待办事项清单来结束本篇文章:

整合这些新功能还有不少工做要作,特别是在开发者工具和编辑器方面。

要发掘 GraphQL 的所有潜力,还有不少事情要作。在 Apollo 团队,咱们正在尽咱们所能来作这件事情,但单独的一我的,团队或组织不可能独自完成这个目标。为了实现将来的愿景,咱们须要共同合做,共同构建出全部这些解决方案。

不管咱们在哪里,有一点是明确的:GraphQL 已经成千上万的公司的变革技术,而这只是一个开始! 我火烧眉毛地想知道在接下来的两年,五年和十年中编写应用程序会是什么样子,由于这将是难以想象的。

参与其中

若是你像 Apollo 同样对 GraphQL 的潜力感兴趣,请考虑加入咱们的社区。咱们已经组建了一个帮助页面 来帮助你入门。

GraphQL 峰会上的其余会议即将发布!在Twitter上关注 @graphqlsummit 或订阅 Apollo 的 Youtube 频道 以获取最新内容。

终于写完了……

相关文章
相关标签/搜索