GraphQL 是一种开源查询语言和服务器端运行时,用于指定客户端应如何与应用程序编程接口 (API) 交互。
GraphQL 为表述性状态转移 (REST) 和 RESTful API 提供了一种高效、更灵活的替代方案,并解决了 REST 的一些限制。例如,提供通过单个查询更准确地定位资源的能力。
GraphQL 使用直观的语法,使客户端能够向 API 发送单个 GraphQL 查询并准确接收所需的数据(而不是访问具有大量参数的复杂端点)。这种更高效的数据获取方式可以提高系统性能,方便开发人员使用。
这使得 GraphQL 特别适用于在前端需求快速变化的复杂环境中构建 API。REST 和 GraphQL API 本身并无优劣之分;它们是适合不同任务的不同工具。
2010 年代初,Facebook 经历了巨大的增长和转型。但是,不断增长的用户群和日益复杂的移动应用程序环境使其现有的 RESTful 方法(该方法需要多次往返不同的 API 端点才能获取所有必要的查询数据)变得不可持续。
REST API 无法处理复杂的数据驱动的用户接口,经常遇到延迟问题,而且数据效率低下,特别是对于数据套餐有限或昂贵的移动用户而言。
为了应对这些挑战,Facebook 工程师开发了 GraphQL(以及单页应用程序平台 React),并于 2015 年将 GraphQL 作为开源解决方案发布。最终,Facebook 于 2018 年将该服务移至 GraphQL 基金会,GraphQL 基金会由 AWS、Gatsby、Intuit 和 IBM 等成员公司组成。
GraphQL 架构的声明式数据获取功能围绕多个关键组件和流程展开,每个组件和流程在数据处理中发挥着独特的作用。
其中包括:
GraphQL 依赖于强类型系统,其中所有数据类型都以 GraphQL 模式定义语言 (SDL) 记录。类型化模式规定了可以在 API 中查询的数据类型,以及类型与用户可用的操作之间的关系。
换句话说,它们定义了 API 的功能以及客户端可以交互的数据的形式。此架构的配置最终决定了 API 的使用方式。当查询传入时,架构用于请求验证,GraphQL API 仅执行经过验证的查询。
模式中的每个字段都由解析器支持,该解析器填充数据并确定对一组字段的响应。解析器可以从数据库、云服务或几乎任何其他来源检索数据,提供将 GraphQL 操作(例如查询、转变或订阅)转换为数据的指令。
当查询字段启动时,系统会生成对相应解析器的调用,以生成下一个值。如果字段生成标量值(例如,字符串或数字),则执行完成。如果字段生成对象值,则查询包含该对象的更多字段。此过程一直持续到只剩下标量字段为止。
解析器还有助于数据格式化并帮助系统将来自各种数据源的信息拼接在一起。
数据查询是客户端向 GraphQL 服务器发出的请求;它指定客户端想要获取哪些数据。查询在查询类型中定义,它是代码中的一个特殊对象,它定义了客户端可以针对服务器执行的每个请求的顶级入口点。每种查询类型还定义了每个入口点的名称和返回类型。
当查询传入时,GraphQL 会根据模式定义对其进行验证,然后运行查询(假设查询有效)。查询的结构通常反映了响应数据的结构,从而使数据要求明确且可预测。
转变是指在服务器上创建、更新或删除数据的 GraphQL 操作。其类似于 RESTful API 中的 POST、PUT、PATCH 和 DELETE 操作。虽然用户无需身份验证即可访问某些查询,但转变始终需要身份验证(例如,通过使用 API 令牌)。
与查询的工作原理类似,GraphQL 转变是根据模式及其定义进行验证的。验证并启动转变后,服务器将立即返回 JSON 响应。
尽管 GraphQL API 已成为一种更高效、更灵活的替代方案,但 REST 长期以来一直是 API 架构的标准。REST 是一种用于网络超媒体应用程序的结构化架构风格,旨在使用可缓存、无状态的客户端/服务器通信协议(通常是 HTTP)。
在 GraphQL 和 REST 之间进行选择主要是为了确定哪种工具最适合手头的工作。GraphQL 和 REST 都允许客户端与服务器通信并请求数据,但存在一些关键差异,这导致了 GraphQL 系统的激增。
REST API 是围绕资源(例如,客户端可访问的任何类型的对象、数据或服务)设计的,并通过为每个资源提供不同的端点 (URL) 来工作。它们使用固定的数据结构来确定向客户端提供的资源的形状和大小。
当客户端请求资源时,服务器会发回包含与该资源相关的所有数据的完整数据集。如果客户端只需要数据的子集,它仍然会收到所有数据(过度获取);如果客户端需要跨多个资源的数据,则由于初始请求中的数据检索不足(获取不足),通常必须进行多个 API 调用。
但是,GraphQL 使用单个端点来提供完整且易于理解的数据描述。GraphQL 查询可以访问资源属性并跟踪资源之间的引用。这使客户端能够从单个 API 请求有效负载中获取所需的所有数据,并避免过度获取和获取不足的问题。
在 REST 架构中,更改数据结构通常要求团队对 API 进行版本控制,以防止系统错误和中断对用户的服务。
这意味着开发人员每次更改结构时都必须创建一个新的端点,从而导致多个 API 版本,并使维护过程复杂化。
GraphQL 免除了版本控制的必要,因为客户端可以在查询中指定要求。如果向服务器添加新字段,不需要这些字段的客户端则不会受到影响。相反,如果字段已弃用,客户端可以继续请求这些字段,直到更新查询为止。
REST API 使用 HTTP 状态代码来指示请求的状态/成功。每个状态代码都有特定的含义。成功的请求会返回 200 状态代码,而客户端错误可能会返回 400 状态代码,服务器错误可能会返回 500 状态代码。
GraphQL 以不同的方式处理错误。每个请求,无论是否导致错误,都会返回 200 OK 状态代码。错误不使用 HTTP 状态代码进行传达;相反,系统会在响应正文中与数据一起传达错误。
这种方法要求客户端解析响应正文以确定请求是否成功,这可能会使调试 GraphQL API 变得有些困难。
REST 本身不支持实时更新。如果 Web 或移动应用程序需要具有 REST API 的实时功能,开发人员通常必须实现长轮询(客户端反复轮询服务器以获取新数据)、服务器发送事件和 WebSocket 等技术,这会增加应用程序的复杂性。
然而,graphQL 本身支持使用订阅进行实时更新。订阅保持与服务器的稳定连接,允许服务器在发生特定事件时向客户端推送更新,并使客户端能够掌握相关的 API 数据。
REST 生态系统非常完善,为开发人员提供了广泛的工具、库、框架和教程。但是,使用 REST API 通常要求团队浏览多个端点并了解每个 API 的独特约定和模式。
GraphQL 相对较新,但 GraphQL 生态系统自推出以来已经取得了巨大的发展,提供了各种可用于前端和后端服务开发的工具和库。
诸如 GraphiQL、Apollo Studio 和 GraphQL Playground 等工具为探索和测试 GraphQL API 提供了强大的浏览器内集成开发环境 (IDE)。此外,GraphQL 对代码生成具有强大的支持,可以简化客户端开发。
REST API 依赖于 HTTP 缓存机制,例如 ETag 和上次修改的标头。缓存策略虽然有效,但实施起来可能很复杂,并且可能无法始终如一地优化所有用例的性能。
由于查询的动态特性,GraphQL 应用程序接口的缓存可能更具挑战性。然而,使用持久化查询、响应缓存和服务器端缓存可以缓解这些挑战,并为 GraphQL 架构提供高效的缓存策略。
自从 GraphQL 过渡到 GraphQL 基金会以来,开发人员已经为各种编程语言创建了实现,包括 JavaScript、Python、Ruby 和 PHP 等。GraphQL API 已被无数企业采用,如 Github、Pinterest、PayPal、Shopify、Airbnb 等,使更多客户能够简化数据规范,减少网络数据传输过多或不足的问题,并提高整体数据获取能力。1
此外,企业和开发人员正在推动 GraphQL 架构的开放联合。在当前的迭代中,GraphQL 联合采用单独的 GraphQL 服务并将它们聚合到单个 GraphQL API 中,该 API 作为所有底层后端数据的入口点并且可促进单个请求数据获取。然而,联合实施仅限于单个供应商。
作为回应,GraphQL 支持者倡导民主化联合,这有利于来自 GraphQL API 和非 GraphQL API 的数据聚合,而不是 GraphQL 专有的聚合。2
在云端运行任务关键型工作量——高性能、企业安全和混合云灵活性,无需重新部署平台。
统筹本地、私有和公有云环境,构建开放、可扩展且安全的基础设施,助您按需灵活运行工作量。
在 AI 时代,充分发挥混合云的价值
1 IBM acquires GraphQL startup StepZen to step up its game in API Management, TechCrunch, 8 February 2023
2 Why GraphQL Needs an Open Federation Approach, The New Stack, 16 November 2023