了解最新技术文章
GraphQL 是 Facebook 从 2012 年开始创建和使用的 API 架构,旨在改进 Facebook 传递 News Feed 数据的方式。自 2015 年开源以来,该技术得到了广泛采用,如今 GraphQL 正在为 Atlassian、Credit Karma、GitHub、Intuit、KLM、Pinterest、Shopify、纽约时报、WordPress 和 Yelp 等公司的 API 提供支持。
Facebook 创建了 GraphQL 作为规范,该规范已在多种技术中实现,例如Node.js、Ruby、Python、PHP、Java和C#。
GraphQL 是一项变革性技术。它需要对 API 设计和 API 测试有新的理解,特别是在性能测试方面。
GraphQL 尝试解决开发人员在使用 API 时遇到的两组问题:通常由 API 返回的数据结构的不可变性质造成的问题,以及递归查询的问题。递归查询是对 API 的连续调用,以创建有用的数据集。让我们看一个说明这些问题的示例场景。
想象一下,我必须实现一个应用程序功能,允许用户根据特定作者搜索书籍,然后发布该作者书籍的详细信息。在本例中,我将使用Open Library发布的公共API。Open Library API 是REST(ful),因此为了根据特定作者获取图书信息,我通过创建 URL 来查询 Open Library 的搜索 API,如下所示:
http://openlibrary.org/search.json?author=charles+bukowski
这将返回与作者 Charles Bukowski 相关的图书数据。响应摘录如下所示:
请注意,API 返回大量数据。有些数据与作者所写的书籍直接相关,但也有一些数据与书籍无关。
我感兴趣的数据点是书名及其相关的 ISBN 编号。当我仔细研究回复时,我确实可以找到每本书的标题和 ISBN 号。(我通过在上面用红色边框突出显示有趣的信息来识别它。)一旦我有了 ISBN 编号,我就可以使用开放图书馆 API 的书籍部分来获取特定书籍的详细信息。
我创建一个像这样的 URL:
https://openlibrary.org/api/books?bibkeys=ISBN:0876850875
API 使用如下所示的 JSON 结构进行响应:
{ “ISBN:0876850875”:{ "bib_key": "ISBN:0876850875", “预览”:“无视图”, "preview_url": "https://openlibrary.org/books/OL17228140M/Post_office", “info_url”:“https://openlibrary.org/books/OL17228140M/Post_office” }}
请注意,上面的示例列表返回一个 JSON 结构,其中包含简单的字符串数据和一些 URL。这些 URL 描述了我可以对 API 进行的调用以获取更多信息。我向 API 提交示例列表中的 info_url 字段描述的 URL:
https://openlibrary.org/books/OL17228140M/Post_office
我得到的响应是包含该书所有详细信息的实际网页的 HTML,如下所示:
为了获取满足我的功能要求所需的信息,我必须访问 API 三次 - 首先,获取作者的书籍,然后根据 ISBN 地址获取书籍详细信息,然后获取所有使用第二次调用提供的 URL 获取图书的详细信息。而且,每次通话的结果是,我不仅得到了感兴趣的信息,而且还收到了很多我不感兴趣的信息。
如果我可以描述我想要的信息,然后只需进行一次查询即可获得我想要的信息,而不是完成所有这些工作,那不是很酷吗?
GraphQL 旨在允许开发人员创建查询,根据 API 表示的对象图来描述响应的数据结构。然后,一旦将查询提交到 GraphQL API,就会根据定义的字段返回响应。下面是此类查询的示例:
询问{ 搜索(作者:“查尔斯·布考斯基”){ 书籍{ 标题 国际标准书号 页数 开头段落 封面艺术 } }}
该查询是用GraphQL 查询语言编写的。该查询的含义是,搜索作者 Charles Bukowski 所写的书籍。对于返回的每本书,显示书名、ISBN 编号、书中页数、开头段落和封面艺术。
查询返回的每个字段都是 API 背后的对象图自定义的。此外,查询的名称“搜索”是自定义的。GraphQL 允许对查询和突变进行不同的命名,只要名称不是 GraphQL 保留字之一即可。(突变是一种更改 API 存储的数据的查询。)
什么是对象图?
对象图是离散数学中的一种结构,用于描述事物以及事物之间的关系。事物的正式术语是节点。描述两个事物之间关系的术语是边缘。
在传统的关系数据库中,数据被组织在表中,表由行和列构成。NoSQL 数据库将数据存储在文档中,其中的数据关系以多级大纲格式描述,类似于学者在书籍或学术论文中组织内容的方式。
另一方面,对象图提供了轻松描述多个节点之间的多种关系的灵活性,如下图所示。
正如您所看到的,虽然使用 REST API 获取图书信息需要多次通过网络返回服务器才能获取满足当前需求所需的数据,但 GraphQL 只需要一次查询即可完成相同的目标。GraphQL 仅返回查询中描述的信息,没有额外的开销。我可以通过更改 GraphQL 查询中描述的字段来更改响应中的数据结构。简而言之,与 REST 相比,使用 GraphQL 不仅将数据交换减少为一次网络传输,而且传输回客户端的数据量也大大减少。而且,虽然 REST 响应中的数据结构是不可变的,但 GraphQL 数据结构却很灵活。
然而,虽然初步观察似乎一切都很好,但性能测试人员在考虑 GraphQL 时需要意识到一个潜在的问题。除非采取预防措施,否则在实现 GraphQL API 时存在产生意外服务器端瓶颈的重大风险。事实上,Netflix 的人员在 2018 年底就发现了这个问题。
适用于 QA 和开发团队的现代测试用例管理软件
下载免费试用版
仅仅因为 GraphQL 只需要客户端和服务器之间的一次网络传输来完成查询请求,并不一定会减少总体网络事务的数量。这也不意味着性能问题可以最小化。让我们看一个说明这种潜在危险的场景。
下面的图 3 描述了客户端和 REST API 之间的典型多请求交互。请注意,该场景说明了对位于全球区域(美国中部)的 REST API 服务器的三个调用,并且每个调用都路由到满足特定请求的特定应用程序。每个履行应用程序都位于与 REST API 服务器不同的全球区域。换句话说,一切都在各处。
虽然网络拓扑不是最佳的,但至少潜在的危险被限制在给定的请求范围内。因此,如果遇到性能问题,很容易追踪。事实上,补救措施可能只需将访问日志中的 URL 与 REST API 服务器中的路由流量进行比较即可。
现在,让我们看一下使用 GraphQL API 将数据检索整合到单个请求中的场景。如下图 4 所示,客户端向 GraphQL API 服务器提交单个查询并获取查询响应中所需的所有数据。
然而,在服务器端的幕后,GraphQL 服务器通过网络对不同位置的不同履行应用程序进行多次调用。GraphQL 服务器中的智能将来自不同数据提供者的数据聚合到单个响应中。因此,客户端网络的单次访问会导致服务器端网络的多次访问,并且任何一次服务器端访问都可能导致显着的网络延迟。这是 Netflix 在实施Monet时首次遇到的问题,Monet 是一个管理公司在外部平台上的营销活动的内部项目。
Netflix 工程师将所有 API 活动整合到一个 GraphQL API URL 中。然而,在幕后,GraphQL 服务器将工作委托给驻留在不同数据中心的各种 REST 服务。表现并不是那么好。补救措施是将所有 REST 服务器移至与 GraphQL 服务器相同的数据中心。由于服务器硬件非常接近,性能显着提高。
Netflix 很幸运能够及时发现并修复问题。然而,其他人可能没有那么幸运,除非在计划性能分析时采取某些预防措施。它与客户端调用 GraphQL 的方式有关。
与 REST 不同,REST 中向代表特定资源的不同 URL 发出请求,客户端通过 HTTP POST 向公开 GraphQL API 的单个 URL 提交对 GraphQL API 的查询。GraphQL API 服务器内部进行后续的路由转发。因此,除非做好准备,否则跟踪请求通过服务器端基础设施的完整路径可能很困难。
当怀疑存在瓶颈时,您根本无法依靠将 HTTP 访问日志中的信息与其他跟踪信息相关联来确定根本原因。至少,您需要在 GraphQL API 的查询请求中提供一个相关 ID,作为在整个 API 中执行时跟踪请求行为的键。
需要了解的重要一点是,监控 GraphQL API 中的性能行为并不像测量客户端请求和响应之间的时间跨度那么简单。性能瓶颈不仅可能出现在服务器端的任何地方,而且监控性能也可能特别令人烦恼,因为请求路由可能是模糊的。需要做好预防准备。这些预防措施对于给定的 GraphQL 实现来说是特殊的。测试准备的关键是详细了解 GraphQL 实现,然后确保能够检测性能瓶颈实例的全面监控有效。
GraphQL 作为公司发布 API 的一种方式越来越受欢迎。该技术提供了一种简洁而灵活的数据管理方法。虽然使用 REST API 可能需要客户端多次访问网络才能获取满足特定需求所需的数据,但 GraphQL 允许客户端仅访问网络一次。GraphQL 还允许客户声明完全满足当前需求的数据结构。与使用 REST 相比,这是一个优势,因为 REST API 中的数据结构是预定义的且不可变的。
然而,GraphQL 并不是解决与 API 实现相关的所有问题的万能药。性能瓶颈可能会发生,而且根本原因可能很难确定。因此,测试从业者与 GraphQL API 开发人员密切合作,建立适当的跟踪机制并创建性能测试,而不仅仅是测量客户端和服务器之间的简单请求和响应时间跨度,这一点非常重要。GraphQL 实现的每个部分都需要进行性能分析。
GraphQL 可以提供很多功能,但为了确保它是一种在企业中有效的技术,必须采取规划和预防措施。
下一篇:性能测试也值得持续测试