PayPal:如何在你的公司扩展 GraphQL?

阅读数:2242 2019 年 11 月 19 日 16:56

PayPal:如何在你的公司扩展GraphQL?

GraphQL 是 REST API 的一种非常流行的替代方案,目前正在席卷开发人员的世界!去年, PayPal 将 GraphQL 引入了技术堆栈,彻底改变了开发人员思考数据、获取数据和构建应用程序的方式。本文作者在一年前曾写过一篇 GraphQL 最佳实践的文章,当时受到了广大读者的欢迎。这篇文章同样也是一篇精彩的总结,可以当作公司部署 GraphQL 的指南。

PayPal:如何在你的公司扩展GraphQL?

图源:graphql.org

我们在 PayPal 构建 GraphQL API 时获得了一系列最佳实践和观察总结,这篇文章就是其中之一。

一年前,我们写了一篇《GraphQL:PayPal Checkout 的成功案例》,内容涵盖了我们从 REST 到 Batch REST 再到 GraphQL 的发展历程。自那时以来很多事情都改变了!这篇文章涵盖了我们在 PayPal 扩展 GraphQL 时学到的所有知识,并可作为你在公司部署 GraphQL 的指南。

一年前,使用 GraphQL 的产品很少。虽然我们在 PayPal Checkout 上取得了成功,但那时还没有相关的基础架构、工具、培训或支持。尽管存在这些缺陷,但 GraphQL 的发展仍像火箭一般一飞冲天。在撰写本文时,我们已经有 50 多个不同的产品在使用 GraphQL!

PayPal:如何在你的公司扩展GraphQL?
在短短 2 年内,PayPal 使用 GraphQL 的产品从 3 种增加到 52 种。

这项新技术的应用速度很快,我们仍在努力跟上步伐。与其他技术变革一样,企业级扩展的重点并不在于水平扩展,或为服务器 / 云计算投入大量资金。扩展人员、工具链和流程是最具挑战性的

了解自己

在部署 GraphQL 之前,重要的是要深入了解你所在的公司,理解你们的身份,你们在做些什么,以及你们的长处与不足。

在 PayPal,我们的产品使用 JavaScript 构建。前端采用 React,后端则是 Node.js。技术栈中还有数百个 Java REST 服务和一些 C++ SOAP 之类的服务。

PayPal 是最早使用 Node 的公司之一,并通过 NodeDay 之类的活动,以及与 The Node Firm 和 NodeSource 的合作,在业界打响了 Node 的品牌。

PayPal:如何在你的公司扩展GraphQL?

2014 年,PayPal 的首个 NodeDay。

2013–2015 年,PayPal 迁移到了 Node。Node 改变了整个公司,改善了我们制造和运输产品的方式。过去,一项简单的内容更改需要数周时间才能部署为单个单体 C++ 应用。如今,开发人员只需要几分钟时间就可以实验、迭代和推出新的产品功能。

PayPal:如何在你的公司扩展GraphQL?

https://vimeo.com/82577994

这不是一夜之间发生的转变,也不是偶然的结果。在 Node 融入 PayPal 之前,Bill Scott 提出了使用 LeanUX 构建产品的愿景,其中迭代和学习是核心要素。在 LeanUX 中,UI 数据是实验性、一次性的。如果实验效果不佳,那就不断迭代!Node.js 是其成功的关键所在。

PayPal:如何在你的公司扩展GraphQL?

Kraken.js

2014 年,我们推出了 Kraken,这是 Express 上的一组库,旨在通过可配置的中间件、默认安全设置、一个 dust.js 渲染器和内容本地化来为你的应用“提供一些帮助”。自那以来,Kraken 的大部分武器都消失了。我们仍使用可配置的中间件和默认安全设置,但与 Web 应用程序相关的所有内容自 2014 年以来发生了很多变化。现在,团队正在构建客户端 React 应用,应用程序是部署到 CDN 的静态文件包,而不是在服务器集群中运行的代码。

对于 API 而言,我们使用 BFF Schema。尽管它们都是专用的,并且允许开发人员迭代,但是它们紧密耦合在一起,并且不能很好地复用。结果是我们有很多团队在反复迭代和构建相同的事物!构建 BFF API 也不是一件容易的事。它们往往包含许多编排逻辑,其中你需要从 5、10、15 个不同的服务中获取数据,规范化这些响应,丢弃其中 95%的响应,然后将数据映射、过滤、分类为所需的样子🙄。编写这样的代码并不能充分提升开发人员的效率。这种紧密的耦合和缺乏复用对我们来说是一个问题。

GraphQL 可以提供帮助吗?答案是肯定的!

在上一篇文章中,我们记录了从 REST 到 Batch REST 再到 GraphQL 的旅程。我们发现它做到了两全其美——开发人员可以快速迭代,API 和 UI 松散耦合,并且代码复用也增加了。

推荐你的公司进行类似的练习。在跳上 GraphQL 这趟高速列车之前,花些时间了解你的过去,回顾自己的发展历程,评估自己的优缺点,并考察 GraphQL 可能带来的帮助。

重设期望

开发人员经验 > 性能

在查阅生产就绪的项目清单之前,我们应该重新设定期望值。当你初次接触 GraphQL 时,能想到的好处往往是:通过网络传输的数据变少了,从而可以实现更快、性能更强的应用。

大型公司会将 GraphQL 置于现有的 REST 服务之上。结果是,你的 GraphQL 查询速度将受限于最慢的 REST 服务。GraphQL 允许你在一次往返中获取所需的一切。如果客户端和服务器之间存在空闲,则可以减少往返并降低延迟。但这并不是所有情况下都能做到的。一段时间后,你将意识到开发人员经验灵活性的好处远比性能更重要。

PayPal:如何在你的公司扩展GraphQL?

GraphQL 对人类很友好❤

GraphQL 对人类很友好。使用 GraphQL 时,开发人员考虑的是字段,而不是端点、域或复杂的连接。开发人员可以遍历数据图(graph)来选出用户的名字、60x60 的个人资料照片、主要送货地址和信用卡信息,而不必调用 6-10 种不同的服务。新员工都喜欢它。如果你知道 JSON 是什么样子,那么只要去掉双引号和逗号就能查询 GraphQL API 了。你的 UI 开发人员喜欢它,因为它以产品为中心,具有声明性,并有丰富的工具集支持,可以减少集成摩擦并提高信心。

当你将 GraphQL 推荐给公司的领导者和团队时,请重点谈论开发人员经验生产力灵活性。否则你可能会让他们失望。

位于技术栈边缘的 GraphQL

在 PayPal,我们的核心服务由独立的后端团队开发,产品团队则构建 BFF API,以从这些基础核心服务中编排数据。最初,我们认为“GraphQL 应该无处不在”!我们认为过度获取和获取不足的问题将会消失,你可以知道哪些用例使用哪些字段,并能一直追溯回数据库。架构师喜欢这个想法。但我们无法让整个公司停止将开发流程迁移到 GraphQL 上。

经过大量的实验和反思,我们发现GraphQL 在我们技术栈的边缘最能发光发热。GraphQL 以产品为中心,应该受到产品团队的影响(或经他们开发)。GraphQL Schema 应该由产品团队先设计再开发。它们不应该由后端开发人员孤立地设计。GraphQL 可以很好地处理编排工作。因此 GraphQL 最适合你的技术栈边缘位置,并且可以与 REST 协同工作。

我们的朋友(也是前 PayPal 员工)Trevor Livingston 在 Expedia 使用 GraphQL 时也有类似的观察结果。

PayPal:如何在你的公司扩展GraphQL?

GraphQL 的收益会随着你在技术栈中的应用深度增加而递减。我不认为它是微服务的通解。它的甜点在 API 的边缘表层领域。

在你的公司中引入 GraphQL

好了,是时候实现这一目标了!这部分内容是你的公司引入 GraphQL 时要做的准备工作清单。

首先,你需要为产品团队奠定一个基础。GraphQL 这项技术新奇且令人兴奋,有许多开放式问题和见解。几乎没有什么是一成不变的。你有很多选择!

  • 你的 API 开发人员和消费者是什么样的?
  • 谁负责主要工作?他们了解哪些语言?
  • 他们现在是如何构建 API 的?它们是专用的还是通用的?
  • 你要使用现有的框架和工具吗?具体是哪些?
  • 你需要添加公司专属的内容吗?比如身份验证、授权、复查、断路器、自定义 HTTP 状态代码和错误处理?
  • 你将如何执行标准?
  • 你将如何处理错误?

奠定基础

在 PayPal,为 BFF API 和 UI 做出贡献的产品团队已经让 GraphQL 流行了。我们为 GraphQL API 使用 Node.js。与其他许多公司一样,我们使用 Apollo 的开源库和工具。Apollo 有专门的团队来构建和维护这些工具,因此它们在文档编制方面是一流的。我们使用 apollo-server,并分散应用在了 PayPal 专属的的生产就绪环境中,如日志记录和检测、身份验证、错误处理和速率限制等用途。

如果你有任何独特的要求,请创建可与开源库(如 Apollo)共用的模块和插件。不要创建深层抽象或向开发人员隐藏复杂性。要保持简单,什么问题都能靠谷歌查询出来!

请记住,GraphQL 仍然是一个 API。你要确保有足够的日志记录、复查、断路器模式、速率限制和查询复杂性检查。

扩展知识

确保架构师和 API 设计人员都了解 GraphQL,以帮助你扩展设计审查流程并执行标准。他们很可能已经用了很多年来设计 REST API。GraphQL 是不同的。起初你可能会遇到阻力,但要克服它。你需要花时间与他们一起找出差异,并让他们挑战自我,换一种 API 设计方式:

没有版本控制,使用数据图来代替 ID 以创建关系,没有 HATEOAS 链接。当架构师也了解这一技术后,这会给 GraphQL 的推广带来支持。

接下来要思考,如何在公司内推广 GraphQL 的学习?GraphQL 正在快速变化。你创建的任何培训材料都将过时并需要维护成本。所以请依靠外部资源,并向 Moon Moon 这样的培训公司寻求帮助,获取优秀的 GraphQL 课程!

制定标准

架构师入门之后,你需要设定一些设计标准,创建一份文档并在所有地方都引用它,使用诸如 graphql-schema-linter 之类的工具来强制命名约定。

例如:

  • 所有字段都必须有描述或注释;
  • 类型名称,LikeThis。字段名称,likeThis。枚举值,LIKE_THIS;
  • 尽可能使用枚举;
  • 弃用的字段必须有原因;
  • 没有集合或列表后缀(如:使用 cards,而不是 cardList);
  • 优先使用具有突变的输入类型。

然后你需要针对分页做出选择。在你的 Schema 中显示列表的首选方式是什么?基于游标的分页(Cursor-based pagination)吗?

你将如何发现错误?在撰写本文时,GraphQL 的错误处理还不成体系,有很多选项可供选择:

  • 使用默认 errors 数组;
  • 使用自定义属性扩展 errors;
  • Schema 中的 errors 字段;
  • Union 类型。

在 PayPal,我们使用自定义属性扩展 errors。它仍然符合规范,并允许我们在需要时向 errors 添加错误分类和其他元数据,这些我们很喜欢。我们认为其他选项是不可行的,会导致错误被忽略。

身份认证 / 授权

你将如何保护自己的 Schema?

首先,我们保护了整个 Schema,然后意识到我们拥有许多不同权限、不同类型的用户。然后我们创建了一个高阶 auth 函数,可以用来包装一个解析器。最后,我们意识到创建自定义 auth 指令是保护 Schema 的最佳方法。

PayPal:如何在你的公司扩展GraphQL?

Custom @auth directive

在上面的示例中,如果一个查询包含 user 字段,则必须登录该 user,并且 creditCards 需要额外两项权限。因为这是一条指令,所以它在 Schema 中可见,而不是深埋在代码中。API 设计人员和架构师可能不太了解 JavaScript,但也可以在审查时提供帮助。

通过出色的工具链释放潜能

以前我们写过《GraphQL:检测 API 并释放潜能》,解释了 GraphQL 与 REST 相比有何独特优势:你可以更好地了解 API 的使用方式,并在客户集成你的 API 的过程中为他们带来额外的信心,同时避免重大更改的影响。

首先,你可以将延迟、错误和使用情况数据通过管道传输到公司的制图工具。下面是一个 Grafana 仪表板示例:

PayPal:如何在你的公司扩展GraphQL?

每解析器 / 字段的延迟示例

PayPal:如何在你的公司扩展GraphQL?

来自 Marc-Andre Giroux 的讨论

因为你知道哪些客户请求哪些字段,所以你可以在弃用某些字段时主动通知他们。在 PayPal,我们发现产品团队变得积极主动,小规模交付更改后,更有可能提升迁移速度。大型程序和具有复杂计划流程的大型迁移可能会令人望而生畏,并破坏开发人员的工作流程。

我们推荐的其他工具包括:

graphql-playground,用于测试开发模式下的查询;
https://github.com/prisma-labs/graphql-playground

graphql-schema-linter,用于强制执行 Schema 命名约定;
https://github.com/cjoudrey/graphql-schema-linter

eslint-plugin-graphql,用于 linting 客户端查询;
https://github.com/apollographql/eslint-plugin-graphql

graphql-doctor,用于 PR 状态检查。
https://github.com/cap-collectif/graphql-doctor

购买与构建

在 PayPal,我们最近开始使用 Apollo Platform,产品团队的反馈非常好!Apollo Graph Manager 提供的仪器工具可显示字段级别的深刻见解,提升对重大更改的信心,提供查询白名单,并为每个字段提供 linting 和内联 SLA 计时来简化客户集成工作。

PayPal:如何在你的公司扩展GraphQL?

https://www.apollographql.com/platform/

Apollo Graph Manager 不是免费的。我们可以自己构建这种工具吗?也许可以,但不会那么完美。我们没有 GraphQL 基础架构团队。我们并不想等待 12-18 个月来构建同级别的事物,还要花精力维护它。我们现在就想兑现 GraphQL 的承诺!对比购买与构建的路线,购买 Apollo Platform 的决策明显胜出。我们建议你也考虑一下。

投资 GraphQL

如果你的公司正在使用 GraphQL,则应该参与 GraphQL 的发展,并为其进行投资。与其他公司建立联系,分享经验并将学习成果带回你的公司,这一点很重要。你应该加入 GraphQL 基金会,该基金会包括 PayPal、Facebook、Twitter、AWS、Intuit 和 New York Times 等公司成员。加入 GraphQL 贡献者日之类的小组或当地聚会,或加入 GraphQL 工作组,还可以提交规范提案。

PayPal:如何在你的公司扩展GraphQL?

https://foundation.graphql.org/

PayPal:如何在你的公司扩展GraphQL?

第一次 GraphQL 贡献者日

在企业中扩展 GraphQL 面临的挑战

GraphQL 是很出色的工具,但我们要解决一些关于数据图的组装以及如何衡量成功的问题,才能充分享用它的好处。

许多仓库

在 2012 年之前,PayPal 用的是 C++ 单体仓库。从那时起,我们在许多领域和产品团队中产生了数千个 GitHub 仓库,构成了许多服务和应用程序层。对于使用单体仓库的 Facebook 和 GitHub 这样的公司来说,共享并不是什么大问题。

GraphQL 在许多仓库中都很难用。如果没有诸如存根远程类型之类的自定义技巧,就无法引用或链接本地文件系统中不存在的远程类型。开发人员很难发现或复用其他服务中定义的类型。

数据图的组装

用户希望看到一个可以遍历的单一内聚图,而无需操心许多服务,无需动用许多服务来获取所需的数据。实际上,组装单个图是很困难的。

一种解决方案是 Schema 拼接,其中网关消费底层 GraphQL API 的 Schema 向开发人员显示单个 Schema,还会将传入的查询委派给底层 API。Marc-Andre Giroux 写了一篇出色的文章介绍了 Schema 拼接遇到的挑战。通过 Schema 拼接,网关就有了粘合代码,负责维护类型之间的关系,并确保子查询正确执行。当网关所有者不知道这些类型之间的关系,并且产品团队无法控制这一基础架构时,粘合代码就会出现问题。

Apollo Platform 的解决方案是一种联盟开发范式,使用自定义指令以声明方式将类型链接在一起。它消除了网关中对粘合代码的需求,合理地分离了关注点,并允许你扩展在本地开发中没有的类型。我们可以期待一下,看看业界是否会采用它,以及联盟将如何影响 GraphQL 规范。

如果构建单一数据图是不可行的话该怎么办?在 Paypal,我们为快速迭代和持续学习进行了优化。许多开发人员认为,自己没有必要放慢脚步,与其他成员达成共识并融入更大的集体。这是我们文化的双刃剑。如果单张图是做不到的,我们还可以怎样复用工作成果呢?另一个选项是 GraphQL Modules 和 graphql-component 之类的本地模块。使用本地模块,你可以选择所需的类型和字段,所有代码都在同一进程中运行,于是 Schema 拼接和联盟遇到的许多问题就能解决了。但是,我们有许多相似的端点,并且服务器占用并未减少。你可以接受吗?

这是我们使用 GraphQL 时遇到的最困难的问题。

衡量成功

如前所述,GraphQL 最亮眼的好处是开发人员经验、生产力和灵活性。有时,性能方面可能会有一些收益,但这并不是你可以兑现的承诺。

如何衡量开发人员的经验?如何做到客观而不是胡乱分析一通?如何衡量开发人员的生产力?比较使用 GraphQL 的项目与其他项目的完成时间呢?

这仍然是我们面临的一个挑战。我们与开发人员交流,他们告诉我们工作轻松了许多,但是我们如何量化这一点呢?

喜欢这些挑战吗?

我们中有人会在本月的 GraphQL 峰会上发言。我们很乐意分享有关 GraphQL 的想法和讨论!😊

原文链接
https://medium.com/paypal-engineering/scaling-graphql-at-paypal-b5b5ac098810

评论

发布
用户头像
先把生态和社区完善好吧,蛋疼
2019 年 11 月 20 日 09:16
回复
没有更多了