写点什么

Coursera 的 GraphQL 之旅

  • 2017-12-06
  • 本文字数:2274 字

    阅读完需:约 7 分钟

Bryan Kane 讲述了 Coursera 是如何在他们的生产环境使用 GraphQL 的。以下内容翻译自作者的博客,查看原文: Coursera’s journey to GraphQL

在 Coursera,前端开发人员非常喜欢 GraphQL 的灵活性、类型安全和社区支持,但后端开发人员却不怎么直接接触 GraphQL。

在过去的一年,我们开发了一些工具将 REST API 转成 GraphQL,这样后端开发人员就可以继续开发他们熟悉的 API,而前端开发人员可以通过 GraphQL 访问他们想要的数据。

在这篇文章里,我们将介绍我们的GraphQL 之旅以及在这一过程中经历的成功与失败。

初始调研

Coursera 的 REST API 都是基于资源的,比如课程 API、导师 API、年级 API 等。这些 API 的开发和测试都很容易,而且在后端提供了非常好的关注点分离。不过,随着产品规模的增长,API 的数量也在增长,我们开始面临一系列问题,如性能问题、文档问题和易用性问题。我们发现很多页面需要四到五个网络来回才能获取到必要的数据。

我还记得在 Facebook 推出 GraphQL 时那种激动的心情,我们立刻意识到 GraphQL 将会解决我们的很多问题,我们可以一次性拿到必要的数据,并为 API 提供结构化的文档。但要在客户端完全使用 GraphQL 端点代替 REST 似乎是件不可能的事,因为:

  • 那个时候,我们有超过 1000 个不同的 REST 端点(现在则更多),从 REST 到 GraphQL 的迁移成本是巨大的。
  • 所有后端的服务间通信都使用了 REST API,而且后端服务为前端和其他后端服务暴露出来的是同一套 API。
  • 我们有三种客户端(Web、iOS 和 Android)。

经过调研,我们找到了一种可以采用 GraphQL 的方案——我们决定在 REST API 之上增加一个 GraphQL 代理层。这种方式已经很常见了,并有详细的文档记录,所以这里就不再详述。

在生产环境使用GraphQL

我们先是构建了一个新的GraphQL 处理器,然后在生产环境启动了一个GraphQL 服务器用于向REST 端点发起调用,并将数据展示在演示页面上。经过几天的测试,我们确定这个方案是可行的。

短暂的成功

我们从这个项目中学到了一个教训,就是不要高兴得太早。

GraphQL 服务器在头几天很稳定,但在我们向团队演示数据页面那天,所有的 GraphQL 查询都失败了。这个让我们有点措手不及,因为从上次确认这个方案可行之后,就没有动过 GraphQL 服务器。

后来我们发现,下游的课程目录服务为了修复一个不相关的 bug 回滚到了前一个版本,导致 GraphQL 服务中的 schema 出现不一致。我们很快修复了 schema 问题,但我们也意识到,当 GraphQL 的 schema 规模增长到 1000 个并由 50 多个不同的服务来支撑的时候,要保持一切都同步是不可能的事情。在微服务架构里,如果有多个事实来源(source of truth),那么出现不同步是迟早的事。

自动化流程

于是我们试图寻找如何能够实现单个事实来源的解决方案——我们完全可以将 REST API 作为事实来源,因为我们的 GraphQL schema 就是基于这些 API 定义的。所以,我们需要自动化、决策性地构建我们的 GraphQL 层,体现出当前架构里正在运行的东西,而不是我们的臆想。

幸运的是,我们的 REST 框架为我们提供了所需的一切:

  • 每个服务为我们提供动态的 REST 资源清单。
  • 对于每一种资源,我们可以检查它们的端点和参数(比如,课程可以通过 id 获取到,或者通过导师查询到)。
  • 我们可以收到由我们的 Courier Schema Language 为每个模型定义的 Pegasus Schema。

我们在 GraphQL 服务器上设置了一个任务,每五分钟 ping 一次下游的服务,获取所有必要的信息,然后在 Pegasus Schema 和 GraphQL 类型之间构建一对一的转换层。

接下来,我们使用之前开发的处理器逻辑在 GraphQL 查询和 REST 请求之间建立映射,得到一个全功能的 GraphQL 服务器,其更新速度的落后时间不会超过五分钟。

关联资源

我们使用 GraphQL 最主要的原因之一就是希望能够为页面一次性获取到必要的数据。不过,我们最初的方案只提供了 REST API 到 GraphQL 之间一对一的映射。如果不将资源关联起来,我们仍然需要进行多次 GraphQL 查询。尽管开发者体验得到了提升,但在性能方面并没有获得实际的好处。

我们的 REST API 都是一个个孤岛,但在使用了 GraphQL 之后,模型和资源需要对彼此有所了解,因为它们之间存在必要的关联。

资源之间并不会自动构建链接,所以我们定义了一个简单的注解,开发人员可以将它加在资源上面,用于指定资源之间的关系。例如,一个课程资源需要有一个导师字段,表示教授该课程的导师是谁。我们可以使用课程里的导师 ID 获取导师信息。我们称之为“前向关系”,因为我们知道使用 ID 可以获得哪些导师的信息。

复制代码
courseAPI.addRelation(
"instructors" -> ReverseRelation(
resourceName = "instructors.v1",
finderName = "byCourseId",
arguments = Map("courseId" -> "$id", "version" -> "$version"))

如果我们想从一个资源跳到另一个资源,但又没有显式指定链接,那么可以使用反向查找。比如,为了找出某个用户的某一门课程的注册信息,我们可以在 userEnrollments.v1 资源上调用 byCourseId,这样就可以返回某个用户在某门课程上的注册信息。

有了这些链接,Coursera 的所有数据和资源就形成了一个网络。

结论

我们在 Coursera 的生产环境运行 GraphQL 服务器超过六个月的时间,虽然道路仍然崎岖,但 GraphQL 为我们提供的帮助无所不在。开发人员操作数据变得更加容易,GraphQL 提供的类型安全特性也让我们的网站变得更可靠,使用 GraphQL 加载数据也更快。


感谢徐川对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017-12-06 18:002317
用户头像

发布了 322 篇内容, 共 158.6 次阅读, 收获喜欢 148 次。

关注

评论

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

企业内PAAS建设的经验与教训

Crazy

中间件 PaaS 经验 云原生应用

VuePress 博客之 SEO 优化(一) sitemap 与搜索引擎收录

冴羽

Vue vuepress SEO 博客搭建 sitemap

手把手教程|构建无服务器通用文本识别功能

亚马逊云科技 (Amazon Web Services)

架构

龙蜥开发者说:做开源,兴趣是最好的源动力 | 第1期

OpenAnolis小助手

开源 创作 开发者故事 兴趣是动力

2 月月更获奖名单公布!获奖的小伙伴速速领取奖励啦!

InfoQ写作社区官方

2月月更 热门活动

杜绝不良信息侵害未成年,皮皮APP发起语音社交行业自律书

联营汇聚

好云推荐官丨飞天加速之星怎样选择云服务器ECS?

阿里云弹性计算

阿里云 采购季 好云推荐官

【Python训练营】Python每日一练----第31天: k倍区间

是Dream呀

3月月更

盲盒风潮过后,中国收藏玩具市场该何去何从?

易观分析

盲盒 潮玩

被冰封的 Bug:Fishhook Crash 修复纪实

RTE开发者社区

Dev for Dev fishhook

MongoDB案例分享:如何使用oplog恢复数据

MongoDB中文社区

mongodb

租房小程序

源字节1号

前端开发 后端开发 租房小程序

敏捷小游戏的思考-上篇

LigaAI

团队管理 敏捷实践

我给公司用了这款工具,领导直接给我涨了两千工资

刘祥

后端技术 编程工具

什么是以特性为核心的持续交付|阿里巴巴DevOps实践指南

阿里云云效

云计算 阿里云 研发效能 研发 DevOps实践指南

做毕设用不起GPU?亚马逊云SageMaker免费给你用

亚马逊云科技 (Amazon Web Services)

学习

一文读懂 MongoDB驱动程序 API

MongoDB中文社区

mongodb

经验分享 | 搭建帮助中心的最强攻略

小炮

Hoo虎符研究院| 稳定币的主要分类及发展趋势

区块链前沿News

虎符研究院 稳定币

安全app之PHP代码审计

网络安全学海

网络安全 信息安全 渗透测试 WEB安全 代码审计

你的密钥被我看见了 !逆向获取密钥

H

网络安全 逆向

openGauss社区成立ReleaseManagement SIG

租房小程序

源字节1号

前端开发 后端开发 租房小程序

基于深度学习的时间序列预测

云智慧AIOps社区

关于知识库:你需要知道的一切

小炮

聊聊 kerberos 的 kinit 命令和 ccache 机制

明哥的IT随笔

数据安全 kerberos

基于微信小程序的大学社团平台的可研方案

CC同学

fastposter v2.6.0 发布 电商海报生成器

物有本末

fastposter 海报生成器 电商海报

基于WEB快速开发平台的轻量ERP

雯雯写代码

ERP 快速开发平台

如何从头到脚彻底解决一个MySQL Bug

华为云开发者联盟

MySQL 数据库 华为云 bug GaussDB(for MySQL)

聊聊编程中的 “魔数”

程序员鱼皮

Coursera的GraphQL之旅_语言 & 开发_Bryan Kane_InfoQ精选文章