了解最新技术文章
GraphQL 是一种 API 架构,从 2012 年开始在 Facebook 创建和使用,以改进其提供动态消息数据的方式。自 2015 年开源以来,该技术得到了广泛的采用,如今 GraphQL 正在为 Atlassian、Credit Karma、GitHub、Intuit、KLM、Pinterest、Shopify、纽约时报、WordPress 和 Yelp 等公司的 API 提供支持。
Facebook创建了GraphQL作为规范,该规范已在许多技术中实现,例如Node.js,Ruby,Python,PHP和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 编号,我就可以使用 Open Library API 的书籍部分来获取特定书籍的详细信息。
我创建一个 URL,如下所示:
https://openlibrary.org/api/books?bibkeys=ISBN:0876850875
API 使用如下所示的 JSON 结构进行响应:
{ "ISBN:0876850875": { "bib_key": "ISBN:0876850875", "preview": "noview", "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 后,将根据定义的字段返回响应。下面是此类查询的示例:
query{ search(author: "charles bukowski") { books { title isbn num_of_pages opening_paragraph cover_art } } }
此查询是用 GraphQL 查询语言编写的。查询的意思是,搜索作者查尔斯·布科夫斯基 (Charles Bukowski) 撰写的书籍。对于退回的每本书,请显示书名、ISBN 编号、图书页数、开头段落和封面艺术。
查询返回的每个字段都自定义为 API 背后的对象图。此外,查询的名称 search 是自定义的。GraphQL 允许对查询和变更进行不同的命名,只要该名称不是 GraphQL 保留字之一。(突变是更改 API 存储的数据的查询。
什么是对象图?
对象图是离散数学中的一种结构,用于描述事物和事物之间的关系。事物的正式术语是节点。描述两件事之间关系的术语是边缘。
在传统的关系数据库中,数据以表的形式进行组织,这些表使用行和列进行结构化。NoSQL数据库将数据存储在文档中,其中的数据关系以多级大纲格式描述,类似于学者在书籍或学术论文中组织内容的方式。
另一方面,对象图提供了轻松描述多个节点之间的多种关系的灵活性,如下图所示。
正如你所看到的,虽然使用 REST API 获取书籍信息需要多次通过网络返回服务器以获取满足手头需求所需的数据,但 GraphQL 只需要一个查询即可完成相同的目标。GraphQL 仅返回查询中描述的信息,没有额外的开销。我可以通过更改 GraphQL 查询中描述的字段来更改响应中的数据结构。简言之,与REST相比,使用GraphQL时,不仅将数据交换减少到一次网络,而且流回客户端的数据量也大大减少。而且,虽然 REST 响应中的数据结构是不可变的,但 GraphQL 数据结构是灵活的。
然而,虽然在最初的观察中,事情看起来一切顺利,但性能测试人员在考虑 GraphQL 时需要注意一个潜在的问题。除非采取预防措施,否则在实现 GraphQL API 时存在造成意外服务器端瓶颈的重大风险。事实上,这个问题是在 2018 年底由 Netflix 的人们发现的。
面向 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 服务器中的内部执行后续路由转发。因此,除非做好充分准备,否则很难跟踪请求通过服务器端基础结构的完整路由。
当怀疑存在瓶颈时,您根本无法依靠将 HTTP 访问日志中的信息与其他跟踪信息相关联来确定根本原因。至少,您需要在向 GraphQL API 的查询请求中提供相关 ID 作为密钥,用于跟踪请求在整个 API 中执行时的行为。
需要了解的重要一点是,在 GraphQL API 中监控性能行为并不像测量客户端请求和响应之间的时间跨度那么简单。性能瓶颈不仅可能发生在服务器端的任何位置,而且监视性能可能特别令人烦恼,因为请求路由可能很模糊。需要做好预防性准备。这些预防措施对于给定的 GraphQL 实现来说是特殊的。测试准备的关键是详细了解 GraphQL 实现,然后确保能够检测性能瓶颈实例的全面监控是有效的。
GraphQL 作为公司发布 API 的一种方式越来越受欢迎。该技术提供了一种简洁而灵活的数据管理方法。虽然使用 REST API 可能需要客户端通过网络进行多次旅行以获取满足特定需求所需的数据,但 GraphQL 允许客户端对网络进行一次旅行。GraphQL 还允许客户端声明完全满足当前需求的数据结构。与使用 REST 相比,这是一个优势,因为 REST API 中的数据结构是预定义的且不可变的。
然而,GraphQL 并不是消除与 API 实现相关的所有问题的灵丹妙药。可能会出现性能瓶颈,并且难以确定根本原因。因此,测试从业者必须与 GraphQL API 开发人员密切合作,以建立适当的跟踪机制,并创建性能测试,而不仅仅是测量客户端和服务器之间的简单请求和响应时间跨度。GraphQL 实现的每个部分都需要进行性能分析。
GraphQL 提供了很多东西,但为了确保它是一种在企业中有效的技术,必须采取规划和预防措施。