REST 与 GraphQL API 的优缺点

2025-05-28

REST 与 GraphQL API 的优缺点

请注意,该文档是由我的同事 Derric 编写的,但我们在同一个地方写博客。

自从 Facebook 推出 GraphQL 以来,它作为 REST API 的替代方案席卷了 API 领域。GraphQL 解决了 API 开发者和用户在 RESTful 架构中发现的诸多问题。然而,它也带来了一系列需要评估的新挑战。由于 GraphQL 不仅仅是 RESTful API 的进化替代品,本文将深入探讨两者的优缺点,以及 GraphQL 何时适合您的应用程序。

历史

在 RESTful API 出现之前,我们有 RPC、SOAP、CORBA 和其他不太开放的协议。许多 REST 之前的 API 需要复杂的客户端库来通过网络序列化/反序列化有效负载。与今天的 RESTful API 相比,一个根本的区别是 SOAP 是通过 WSDL(Web 服务描述语言)使用正式契约强类型的。这可能会严重破坏互操作性,因为即使删除 32 位整数限制以接受 64 位长整数也意味着破坏上游客户端。SOAP 不是一种架构,而是一个完整的协议实现,包括安全性、错误处理、ACID 事务等。部分复杂性是由于 SOAP 中嵌入了许多抽象层。例如,SOAP 能够在 HTTP、TCP、UDP 等上运行。虽然协议实现提供了许多抽象,但客户端和服务器之间应用程序和数据层的严格契约在两者之间产生了紧密耦合。

RESTful 架构于 2000 年推出,它是一种更简单的方式,仅使用无处不在的 HTTP 协议,无需额外的层,以无状态和类型无关的方式实现机器与机器之间的通信。这使得系统能够松散耦合,并且对系统之间(例如公司之间)的合同变更具有更高的容忍度。

今天休息

REST API 已成为企业部署 API 和启动开发者平台的事实上的标准。REST 的魅力在于,开发者使用他人的 API 时无需任何特殊的初始化或库。请求可以通过 cURL 和 Web 浏览器等常用软件轻松发送。

REST 使用标准的 CRUD HTTP 动词(GET、POST、PUT、DELETE),并利用 HTTP 约定,以数据资源(HTTP URI)为中心,而不是试图对抗 HTTP。因此,拥有资源的电子商务api.acmestore.com/items可以表现得类似于拥有资源的银行api.examplebank.com/deposits。两者都可能需要对该资源进行 CRUD 操作,并且倾向于缓存查询(即和GET api.acmestore.com/items都会GET api.examplebank.com/transactions被缓存)。新 API 的第三方开发人员只需推断数据模型,其余部分留给 HTTP 约定,而不是深入研究数千个操作。换句话说,与 SOAP 相比,REST 与 HTTP 和 CRUD 的耦合度更高,但提供了松散的数据契约。

REST 的问题

随着越来越多的 API 投入生产并扩展到极致,RESTful 架构中的某些问题逐渐显露出来。甚至可以说,GraphQL 介于 SOAP 和 REST 之间,并互相借鉴。

服务器驱动的选择

在 RESTful API 中,服务器创建资源的表示形式以响应客户端。

但是,如果客户想要一些特定的东西,比如返回某个用户的朋友的朋友的名字,而他们的工作是工程师,那该怎么办呢?

使用 REST,您可能会得到类似以下内容:

GET api.example.com/users/123?include=friend.friend.name&friend.friend.ocupation=engineer
Enter fullscreen mode Exit fullscreen mode

GraphQL 允许你以更清晰的方式表示此查询:

{
 user(id: 123) {
   friends {
     friends(job: "engineer") {
       name
     }
   }
 }
}
Enter fullscreen mode Exit fullscreen mode

获取多个资源

GraphQL 的主要优势之一是让 API 更简洁。我们很多人都见过这样的 API,首先需要GET /user通过端点逐个获取每个好友,然后才能获取GET /user/:id/friend/:id他们,这会导致 N+1 次查询,这也是 API 和数据库查询中一个众所周知的性能问题。换句话说,RESTful API 调用在客户端上需要进行链式调用,然后才能最终形成显示结果。GraphQL 可以通过允许服务器在单个查询中为客户端聚合数据来减少这种情况。

更深入的分析

虽然 API 分析对 GraphQL API 来说也有不利之处,因为市面上可用的工具非常少。但支持 GraphQL API 的工具可以提供比 RESTful API 更深入的查询洞察。

GraphQL 的问题

缓存

HTTP 规范内置了缓存功能,RESTful API 可以利用这一点。与缓存相关的 GET 和 POST 语义定义明确,浏览器缓存、中间代理和服务器框架均可遵循。可以遵循以下准则:

  • GET 请求可以缓存
  • GET 请求可以保留在浏览器历史记录中
  • GET 请求可以添加书签
  • GET 请求是幂等的

GraphQL 不遵循 HTTP 缓存规范,而是使用单个端点。因此,对于可缓存的非可变查询,开发者需要确保正确实现缓存。缓存必须使用正确的键,这可能包括检查主体内容。

虽然您可以使用理解 GraphQL 语义的 Relay 或 Dataloader 等工具,但它们仍然无法涵盖浏览器和移动缓存等内容。

减少无共享架构

RESTful API 的魅力在于它们能够很好地补充无共享架构。例如,Moesif 有一个api.moesif.com/v1/search端点和一个api.moesif.com/v1/alerting端点。对外公开,​​这两个端点看起来就像两个不同的 REST 资源。但在内部,它们指向位于独立计算集群上的两个不同的微服务。搜索服务用 Scala 编写,警报服务用 NodeJS 编写。通过主机名或 URL 路由 HTTP 请求的复杂性远低于检查 GraphQL 查询并执行多个连接操作。

暴露任意请求

虽然 GraphQL 的主要优势在于允许客户端仅查询所需的数据,但这也可能带来问题,尤其是在组织无法控制第三方客户端查询行为的开放 API 中。必须格外小心,确保 GraphQL 查询不会导致昂贵的连接查询,从而降低服务器性能,甚至导致服务器遭受 DDoS 攻击。RESTful API 可以进行限制,以匹配所使用的数据模型和索引。

查询的严格性

GraphQL 移除了在 API 之上自定义查询 DSL 或副作用操作的功能。例如,Elasticsearch API 是 RESTful 的,但也拥有非常强大的 Elasticsearch DSL 来执行高级聚合和指标计算。此类聚合查询在 GraphQL 语言中建模可能更加困难。

不存在监控

RESTful API 的优势在于,它遵循 HTTP 规范,就像网站一样,用于处理资源。这使得许多工具能够探测 URL,例如,api.moesif.com/health如果 URL 不正常,则会返回 5xx。对于 GraphQL API,除非您支持将查询作为 URL 参数,否则您可能无法使用此类工具,因为大多数 ping 工具不支持 HTTP 和请求正文。

除了 ping 服务之外,很少有 SaaS 或开源工具支持 API 分析或对 API 调用进行更深入的分析。客户端错误在 GraphQL API 中显示为 200 OK。现有的预期 400 错误的工具将无法正常工作,因此您可能会错过 API 上发生的错误。然而,与此同时,赋予客户端更大的灵活性也需要更多工具来捕获和理解 API 中的问题。

结论

GraphQL API 是一项令人兴奋的新技术,但在做出此类架构决策之前,务必了解其利弊。某些 API(例如,实体数量极少且跨实体关系复杂的 API,例如分析 API)可能不适合使用 GraphQL。而拥有众多不同领域对象的应用程序(例如,包含商品、用户、订单、付款等的电商应用)则可能更适合使用 GraphQL。

事实上,GraphQL 与 REST 的比较就像 SQL 技术与 NoSQL 的比较一样。在某些应用中,使用 SQL 数据库建模复杂实体是合理的。而对于其他仅包含“消息”的应用(例如高流量聊天应用或以“事件”为唯一实体的分析 API),使用 Cassandra 之类的工具可能更合适。

但与此同时,我们预计 GraphQL 的使用率将持续增长,这些问题可以通过更好的工具得到解决。对于 GraphQL 来说,深入分析更加有意义,请查看我们在 Moesif 上对 GraphQL 的支持

文章来源:https://dev.to/xngwng/rest-vs-graphql-apis-the-good-the-bad-the-ugly-34i8
PREV
字体行业不想让你知道的秘密
NEXT
使用 HTML 和 CSS 制作动画内容占位符