写点什么

GraphQL 技术栈概览:如何将所有的功能组合起来

  • 2017-12-18
  • 本文字数:4107 字

    阅读完需:约 13 分钟

本文最初发布于 Apollo 博客,经原作者授权由 InfoQ 中文站翻译并分享。

Facebook 将 GraphQL 作为开源项目发布已经有两年的时间了。从那时算起,社区就以指数级的速度在增长,现在成千上万的公司在生产环境中使用 GraphQL。在 2017 年 10 月举行的 GraphQL 峰会上,我非常荣幸地受邀在第二天演讲。读者可以在 YouTube 上观看完整的视频,也可以通过阅读本文对演讲有一个大致的了解(演讲的演示文稿可以在SlideShare 站点下载——译者注)。

首先,我会简要介绍一下GraphQL 的现状,然后阐述它未来一段时间内的演化会给开发人员带来哪些好处,尤其会重点介绍全栈GraphQL 集成的三个样例:缓存、性能跟踪和模式拼接(schema stitching)。

GraphQL 的与众不同之处是什么?

主要有三个因素使得 GraphQL 在与其他 API 技术的对比中脱颖而出:

  1. GraphQL 有一个很好的查询语言,这是用来描述数据需求(data requirement)的好办法,另外它还具有一个定义良好的模式,它暴露了API 的能力(API capability)。在主流技术中,GraphQL 是唯一一个同时指定了等式两侧的主流技术,它的所有好处都来源于这两个概念的相互作用。
  2. GraphQL 能够帮助我们将 API 的消费者与提供者解耦。在像 REST 这种基于端点的 API 中,所返回数据的形式是由服务器决定的。在 GraphQL 中,数据的形式则是由使用它的 UI 代码所决定的,这样的话会更加自然,能够让我们聚焦于关注点分离,而不是技术。
  3. GraphQL 查询是与使用它的代码息息相关的,所以我们可以将查询视为一个数据获取单元。GraphQL 预先了解 UI 组件的所有数据需求,因此能够实现一些新类型的服务器功能。比如,在某个查询的底层 API 调用中,使用批处理和缓存,这些调用代表了 UI 部分所需的数据,借助 GraphQL 来实现就会变得非常容易。


分离关注点,而不是分离技术:GraphQL 将数据的需求放到了客户端

接下来,我们看一下人们经常提到的关于数据获取的三个方面,然后讨论 GraphQL 如何使用上述特性来对其进行改善。

需要注意的是我所讨论的功能有很大一部分是现在就可用的,还有一部分是将来要实现的。如果这些功能让你感到兴奋的话,那么可以滚动的页面底部了解如何参与。

1. 跨请求缓存

人们经常问到的一个问题就是如何为 GraphQL API 实现跨请求的缓存。在将常规的 HTTP 缓存应用到 GraphQL 上时,会有一些问题:

  • HTTP 缓存通常不支持 POST 请求或较长的 cache key;
  • 请求的多样性通常会意味着更低的缓存命中率;
  • GraphQL 是独立于传输层的,所以 HTTP 并不一定总是有效。

但是,GraphQL 同时带来了众多新的机会:

  • 在访问后端的模式和解析器(resolver)上声明缓存控制信息;
  • 模式方案所带来的自动化细粒度缓存控制,而不需要考虑每个请求的命中率。

在 GraphQL 中我们该如何更好地使用缓存呢,我们又该如何利用这些新机会呢?

应该将缓存功能放在何处?

我们首先需要决定将缓存功能放到何处。最初的设想可能会计划将缓存逻辑放到 GraphQL 服务器里面。但是,像 DataLoader 这样的简单工具无法跨 GraphQL 请求良好地运行,另外将缓存功能放到服务器端的代码中有可能会导致实现变得非常复杂。所以,我们应该将其放到其他的地方。

就像 REST 一样,在 API 层的两侧都进行缓存是非常明智的做法:

  1. 在 GraphQL API 外边的基础设施层缓存整个响应;
  2. 在 GraphQL 服务器之下缓存底层对数据库和微服务访问所获取到的结果。

对于第二项,已有的缓存基础设施依然可用。对于第一项,我们需要在 API 之外创建一个新的分层,它能够以感知 GraphQL 的方式实现诸如缓存这样的功能。从本质上来讲,这种架构能够让我们将复杂性放到 GraphQL 服务器之外:


将复杂性转移到客户端和服务器之间的一个新的层中

我将这个组件称为 GraphQL 网关。在 Apollo 团队中,我们认为这种新的网关层非常重要,每个人都需要将其作为 GraphQL 架构的一部分。

这也是为什么在本年的 GraphQL 峰会期间,我们启动了Apollo Engine ,将其作为第一个GraphQL 网关。

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

正如我在前面的序言中所述,GraphQL 的优势之一就是它有一个巨大的工具生态系统,它们都是通过GraphQL 的查询和模式来运行的。我认为缓存应该按照相同的方式运行,为此我们引入了 Apollo 缓存控制,它使用了 GraphQL 规范内置的一项名为 _ 扩展(extension)_ 的特性,在响应中包含缓存控制信息。

通过我们的 JavaScript 参考实现,很容易就可以在模式中添加缓存控制信息:


通过 apollo-cache-control-js 在模式中定义缓存信息

在这里,我们在 GraphQL 的主要功能之上创建了这个新的缓存控制规范,对这种实现方式我感到很兴奋。它能够以细粒度的方式指定数据的信息,并且利用 GraphQL 的扩展机制将相关的缓存控制信息发送给消费者。在实现方式上,它完全是独立于语言和传输的。

我在 GraphQL 峰会发表完演讲之后, Oleg Ilyenko 发布了一个针对 Sangria 的可运行缓存控制功能,他在维护着 Scala GraphQL 实现。

通过网关实现缓存

现在,我们重新回到 GraphQL 服务器中的缓存控制信息,借助网关,我们能够以一种清晰的方式来实现缓存功能。栈中的每一部分都能在各自的位置发挥作用:


缓存会协调技术栈中的每个组成部分

还有另外一件很酷的事情值得一提,大多数人已经在 GraphQL 技术栈中使用过缓存了:比如在前端使用 Apollo Client 和 Relay 缓存数据。在未来版本的 Apollo Client 中,来自响应中的缓存控制信息将会自动过期来自客户端的旧数据。所以,就像 GraphQL 中的其他组成部分一样,服务器描述了它的功能,客户端指定其数据需求,所有组成部分都能很好地协作。

接下来,我们看一下另外一个跨越整个栈的 GraphQL 功能样例。

2. 跟踪

相对于基于端的系统,GraphQL 能够让前端开发人员以一种更加细粒度的方式来使用数据。他们能够精确地请求想要的数据,忽略不会使用的字段。这样的话,就有机会探测详细的性能信息,并且能够以过去无法实现的方式来进行性能的跟踪。


不要满足于一个不透明的总查询时间——GraphQL 能够让我们获取每个字段详细计时

我们可以说 GraphQL 是第一个能够细粒度获取内部信息的 API 技术。这并不是某项工具做到的——GraphQL 第一次能够让前端开发人员以合法的方式获取每个字段的执行计时,然后让他们基于此修改查询以解决相关的问题。

跨越整个栈进行跟踪

跟踪与缓存类似,协调整个栈才能真正有用。


在提供跟踪信息时,每个组成部分都有其作用,并且都可以参与进来

服务器可以在结果中提供额外信息,就像提供缓存相关的信息类似,网关可以抽取并聚集这些信息。与缓存类似,在服务器中不想关心的复杂功能,都由网关组件负责处理。

在这里,客户端的主要角色将查询与 UI 组件连接起来。这是非常重要的,我们就可以将 API 层的性能与其对前端影响关联起来。我们第一次能够把后端获取数据的性能与它所影响的 UI 组件在页面上显示出来。

GraphQL 跟踪扩展

与缓存非常类似,我们可以借助 GraphQL 的响应扩展功能,以独立于服务器的方式来实现。Apollo Tracing 规范目前已经有了 Node Ruby Scala Java Elixir 实现,该规范定义了 GraphQL 服务器返回计时数据的方式,解析器(resolver)会以一种标准的方式进行解析,其他的工具都可以使用解析得到的性能数据。

我们假设所有 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.js Graphcool Neo4j


最终,拼接会与栈中的每个组成部分关联

客户端也可以加入进来。就像可以通过一个查询加载多个后端的数据,我们同样可以在客户端组合数据源。在最近发布的 Apollo Client 2.0 中新增了状态管理功能,该功能允许我们在一个查询中加载来自客户端状态和任意数量后端的数据。

结论

通过阅读本文或观看演讲,我希望读者能够意识到 GraphQL 工具如今已经非常强大了,未来有非常大的潜力。我们刚刚所接触的只是 GraphQL 抽象和功能的一个皮毛。

最后,我想基于以上的理念分享一个 TODO 列表:

要集成这些新的特性,还有很多工作需要完成,尤其是开发工具和编辑器领域

要释放 GraphQL 的全部潜力,还有很多的事情要做。在 Apollo 团队中,我们正为此竭尽全力,但是没有任何一个人、团队或组织能够完成所有的事情。为了让未来的蓝图实现,我们需要协作工作,将这些解决方案构建出来。

不管怎样,有一件事情是非常清晰的:GraphQL 已经作为一项变革性的技术用到了成千上万的企业中,但这只是开始!我迫不及待地想知道在未来的两年、五年和十年内,我们该如何构建应用,因为这肯定是非常美妙的!

如何参与

如果你像 Apollo 一样相信 GraphQL 的潜力,那么可以参与到社区中来。为了让读者快速起步,我们创建了一个帮助页面

感谢徐川对本文的审校。

2017-12-18 17:053244

评论

发布
暂无评论
发现更多内容

烧录OpenHarmony 3.2(尝鲜版)步骤

离北况归

OpenHarmony OpenHarmony3.2

直播预告丨Hello HarmonyOS进阶课程第四课——ArkUI动画开发

HarmonyOS开发者

HarmonyOS arkui

干货复盘 | 易观分析“出海非洲战略”专题分享

易观分析

非洲战略

昆仑分布式数据库系统简介 之 SQL 标准兼容性和日常维护工作

KunlunBase昆仑数据库

国产数据库

昆仑分布式数据库Sequence功能及其实现机制

KunlunBase昆仑数据库

国产数据库

2022第八届华为软件精英挑战赛全球总决赛圆满落幕,冠军奖金20万!

科技热闻

满满干货!手把手教你实现基于eTS的HarmonyOS分布式计算器

HarmonyOS开发者

HarmonyOS ETS

Apache SeaTunnel(Incubating)与计算引擎的解耦之道,重构API我们做了些什么

Apache SeaTunnel

Apache 大数据 开源 DolphinScheduler workflow

成本节省 50%,10 人团队使用函数计算开发 wolai 在线文档应用

阿里巴巴中间件

阿里云 中间件 函数计算

人人皆为开发者?不可错过的低代码发展新趋势

云智慧AIOps社区

大前端 低代码 数据可视化

10分钟,将微信小程序转换成App

Speedoooo

微信小程序 移动开发 小程序容器 小程序转app

微擎同步粉丝不显示头像和昵称?

智伍应用

微擎 php开源

Apache ShenYu 网关正式支持 Dubbo3 服务代理

阿里巴巴中间件

阿里云 开源 微服务 云原生 dubbo

“双碳”大局中再看业务合同电子化

鲸品堂

节能 提效降本 双碳

手绘图解java类加载原理

华为云开发者联盟

Java 类加载 元数据 类静态

SaaS应用:企业数字化转型性价比最高的方式

小炮

做了5年开源项目,我总结了以下提PR经验!

OpenHarmony开发者

OpenHarmony 开源生态

我们为什么选择使用分布式持续交付新星 Zadig ?

Zadig

DevOps 云原生 CI/CD 软件交付

MySQL-8.0 Group Replication 研究与改造汇总

KunlunBase昆仑数据库

国产数据库 MySQL 数据库

为什么校招面试中“线程与进程的区别”老是被问到?我该如何回答?

宇宙之一粟

线程 进程 5月月更

小程序和App同时拥有?两者兼得的一种技术方案

Speedoooo

微信小程序 APP开发 小程序容器 小程序转app

文档管理:企业进步的重要因素

小炮

文档管理

火山引擎A/B测试私有化实践

字节跳动数据平台

实验 火山引擎 私有化部署 ab测试

netty系列之:epoll传输协议详解

程序那些事

Java Netty 程序那些事 5月月更

谈谈技术能力

阿里巴巴中间件

阿里云 程序员 中间件 技术思考

热烈庆祝“海泰密码技术融合创新中心&数据中心重启安全工程”双中心智能重启用

电子信息发烧客

网络安全 科技 科技企业

多款顶级好用的 Vue 表单设计器测评推荐,可拖拽生成表单

蒋川

Vue Element 组件 表单设计 Ant Design

IET 试水SiFL中文项目 为中国工程师“走出去”创造宝贵机遇

E科讯

数据库系统最佳实践系列 --- 使用 prepared statement

KunlunBase昆仑数据库

国产数据库

什么是显卡?GPU服务器到底有什么作用?

Finovy Cloud

gpu GPU服务器

《阿里云代码安全白皮书》5个维度应对3类代码安全问题

阿里云云效

云计算 阿里云 代码管理 代码托管 代码安全

  • 扫码加入 InfoQ 开发者交流群
GraphQL技术栈概览:如何将所有的功能组合起来_Facebook_Sashko Stubailo_InfoQ精选文章