11 月 19 - 20 日 Apache Pulsar 社区年度盛会来啦,立即报名! 了解详情
写点什么

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

  • 2019-11-19
  • 本文字数:6231 字

    阅读完需:约 20 分钟

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

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



图源:graphql.org


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


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


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



在短短 2 年内,PayPal 使用 GraphQL 的产品从 3 种增加到 52 种。


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


了解自己

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


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


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



2014 年,PayPal 的首个 NodeDay。


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



https://vimeo.com/82577994


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



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 允许你在一次往返中获取所需的一切。如果客户端和服务器之间存在空闲,则可以减少往返并降低延迟。但这并不是所有情况下都能做到的。一段时间后,你将意识到开发人员经验灵活性的好处远比性能更重要。



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 时也有类似的观察结果。



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 的最佳方法。



Custom @auth directive


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


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

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


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



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



来自 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 计时来简化客户集成工作。



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 工作组,还可以提交规范提案。



https://foundation.graphql.org/



第一次 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-19 16:564238
用户头像
王文婧 InfoQ编辑

发布了 126 篇内容, 共 66.7 次阅读, 收获喜欢 269 次。

关注

评论 3 条评论

发布
用户头像
11
2021-02-04 14:21
回复
用户头像
先把生态和社区完善好吧,蛋疼
2019-11-20 09:16
回复
11
2021-02-04 16:36
回复
没有更多了
发现更多内容

Java中的重载和重写的区别

共饮一杯无

Java 10月月更 重载重写

技术分享 | 接口自动化如何处理 Form 请求?

霍格沃兹测试开发学社

区块链游戏dapp系统开发游戏链改模式定制

开发微hkkf5566

Grafana:灵活的配置

琦彦

配置 Grafana 10月月更

HashSet源码全方位解读

知识浅谈

10月月更

Qt | 线程 QThread

YOLO.

c++ qt 10月月更

免安装免配置环境的免费 ios 调试工具 sib 来啦

霍格沃兹测试开发学社

Zadig 完成 100% 开源:开启软件交付 3.0 时代

霍格沃兹测试开发学社

编程语言中 null 引用的十亿美元错误趣谈

Jerry Wang

Java JavaScript SAP abap 10月月更

QtCreator配置protobuf环境

中国好公民st

qt Qt Creator 10月月更

Docker load 大镜像(17G) 报错no space left on device

琦彦

Docker 10月月更 Base Device Size

通过linux-PAM实现禁止root用户登陆的方法

京东科技开发者

数据库 Linux 公有云 云主机 linux-PAM

Java基础(四)| 数组及内存分配详解

timerring

Java 数组 内存分配 10月月更

20221013

留白的艺术

测试人生 | 二线城市年薪30W+,疫情之下涨薪超过100%,是怎么做到的?

霍格沃兹测试开发学社

技术分享 | 如何使用代理配置快速定位接口测试脚本问题?

霍格沃兹测试开发学社

技术分享 | 接口自动化中如何完成接口加密与解密?

霍格沃兹测试开发学社

Qt | 实现动态创建多个Tab页,页中动态创建多个子部件

YOLO.

qt 10月月更 C++

技术分享 | 接口自动化测试如何进行认证?

霍格沃兹测试开发学社

技术分享 | 接口自动化测试中,如何做断言验证?

霍格沃兹测试开发学社

Java数组详解

共饮一杯无

Java 数组 10月月更

技术分享 | 接口测试中,请求超时该怎么办?

霍格沃兹测试开发学社

专访北大荆琦:产业前沿进课堂,通过产学合作培养开源贡献者

Lily

SAP UI5 OData谣言粉碎机:极短时间内发送两个 Odata request,前一个会自动被 cancel 掉吗

Jerry Wang

JavaScript 前端开发 SAP UI5 ui5 10月月更

从URL输入到页面展现到底发生什么?

loveX001

JavaScript

西安交大谢涛:云上做实验,让计算机教学实现质的飞跃

Lily

技术分享 | 接口自动化测试中,文件上传该如何测试?

霍格沃兹测试开发学社

PayPal:如何在你的公司扩展GraphQL?_前端_Mark Stuart_InfoQ精选文章