比较 API 架构风格:SOAP vs REST vs GraphQL vs RPC

疑惑一号疑惑一号 in 后端 2022-11-06 10:55:03

两个独立的应用程序需要一个中介来相互交谈。因此,开发人员经常构建桥梁——应用程序编程接口——以允许一个系统访问另一个系统的信息或功能。

为了快速、大规模地集成应用程序,API 是使用协议和/或规范来实现的,以定义通过网络传递的消息的语义和语法。这些规范构成了 API 架构。

随着时间的推移,已经发布了不同的 API 架构风格。它们中的每一个都有自己的标准化数据交换模式。多种选择引发了关于哪种建筑风格最好的无休止的争论。

API 发展史

word-image-52.png
今天,许多 API 消费者将 REST 称为“和平的 REST ”,并为 GraphQL 欢呼,而十年前则是一个相反的故事,REST 成为取代 SOAP 的赢家。这些观点的问题在于,他们片面地选择了一项技术本身,而不是考虑其实际属性和特性如何与当前情况相匹配。
在本文中,我们将保持客观,按照出现的顺序讨论四种主要的 API 样式,比较它们的优缺点,并突出它们各自最适合的场景。
word-image-53.png

远程过程调用 (RPC):调用另一个系统上的函数

远程过程调用是允许在不同上下文中远程执行函数的规范。RPC 扩展了本地过程调用的概念,但将其置于 HTTP API 的上下文中。

最初的 XML-RPC 存在问题,因为确保 XML 有效负载的数据类型很困难。因此,后来 RPC API 开始使用更具体的 JSON-RPC 规范,该规范被认为是 SOAP 的更简单替代方案。gRPC 是 Google 于 2015 年开发的最新 RPC 版本。gRPC 具有对负载均衡、跟踪、健康检查和身份验证的可插拔支持,非常适合连接微服务。

RPC 的工作原理

客户端调用远程过程,将参数和附加信息序列化为消息,并将消息发送到服务器。收到消息后,服务器反序列化其内容,执行请求的操作,并将结果发送回客户端。服务器存根和客户端存根负责参数的序列化和反序列化。
word-image-54.png

RPC 优点

直接和简单的交互。RPC 使用 GET 获取信息并使用 POST 获取其他所有信息。服务器和客户端之间的交互机制归结为调用端点并获得响应。

易于添加的功能。如果我们对 API 有新要求,我们可以轻松添加另一个端点来执行此要求:1)编写一个新函数并将其扔在端点后面,2)现在客户端可以访问该端点并获取满足设定要求的信息.

高性能。轻量级负载在网络上很容易提供高性能,这对于共享服务器和在工作站网络上执行的并行计算很重要。RPC 能够优化网络层并使其非常高效,每天在不同的服务之间发送大量消息。

RPC 缺点

与底层系统的紧密耦合。API 的抽象级别有助于其可重用性。它与底层系统越紧密,它对其他系统的可重用性就越低。RPC 与底层系统的紧密耦合不允许在系统中的函数和外部 API 之间存在抽象层。这引发了安全问题,因为很容易将有关底层系统的实现细节泄漏到 API 中。RPC 的紧耦合使得可伸缩性要求和松耦合的团队难以实现。因此,客户端要么担心调用特定端点的任何可能的副作用,要么尝试找出要调用的端点,因为它不了解服务器如何命名其函数。

可发现性低。在 RPC 中,无法自省 API 或发送请求并开始了解根据其请求调用什么函数。

功能爆炸。创建新功能非常容易。因此,我们没有编辑现有的,而是创建了新的,最终会产生大量难以理解的重叠功能。

RPC 用例

RPC 模式在 80 年代左右开始使用,但这并不会自动使其过时。Google、Facebook ( Apache Thrift ) 和 Twitch ( Twirp ) 等大公司正在内部使用 RPC 高性能变量来执行极高性能、低开销的消息传递。他们庞大的微服务系统要求内部通信清晰,同时安排在短消息中。

命令 API。RPC 是向远程系统发送命令的正确选择。例如,Slack API 非常注重命令:加入频道、离开频道、发送消息。因此,Slack API 的设计者将其建模为类似 RPC 的风格,使其小巧、紧凑且易于使用。

用于内部微服务的客户特定 API。由于单个提供者和消费者之间的直接集成,我们不想像 REST API 那样花费大量时间通过网络传输大量元数据。凭借高消息率和消息性能,gRPC 和 Twirp 是微服务的有力案例。在底层使用 HTTP 2,gRPC 能够优化网络层并使其非常高效,每天在不同的服务之间发送大量消息。但是,如果您的目标不是高网络性能,而是发布高度独特的微服务的团队之间的稳定 API 联系,REST 将确保这一点。

简单对象访问协议 (SOAP):使数据作为服务可用

SOAP 是一种 XML 格式的、高度标准化的 Web 通信协议。SOAP 在 XML-RPC 发布一年后由 Microsoft 发布,从中继承了很多东西。当 REST 紧随其后时,它们首先被并行使用,但很快 REST 赢得了流行度竞赛。

SOAP 的工作原理

XML 数据格式拖累了很多形式。再加上海量的消息结构,它使 SOAP 成为最冗长的 API 风格。

SOAP 消息由以下部分组成:

开始和结束每条消息的信封标签,
包含请求或响应的主体
如果消息必须确定任何细节或额外要求,则为标头,以及
通知在整个请求处理过程中可能发生的任何错误的错误。
word-image-55.png
SOAP API 逻辑是用 Web 服务描述语言 (WSDL) 编写的。该 API 描述语言定义了端点并描述了所有可以执行的过程。这允许不同的编程语言和 IDE 快速建立通信。

SOAP 支持有状态和无状态消息传递。在有状态的场景中,服务器存储接收到的信息,这些信息可能非常繁重。但这对于涉及多方和复杂交易的操作是合理的。

SOAP 专家

语言和平台无关。创建基于 Web 的服务的内置功能允许 SOAP 处理通信并使响应与语言和平台无关。

绑定到多种传输协议。SOAP 在传输协议方面很灵活,可以适应多种场景。

内置错误处理。SOAP API 规范允许返回带有错误代码及其解释的 Retry XML 消息。

许多安全扩展。SOAP 与 WS-Security 协议集成,满足企业级事务质量。它在交易内部提供隐私和完整性,同时允许在消息级别上进行加密。
word-image-56.png

SOAP 缺点

如今,许多开发人员对必须集成 SOAP API 的想法感到不寒而栗,原因有很多。

仅限 XML。SOAP 消息包含大量元数据,并且只支持请求和响应的详细 XML 结构。

重量级。由于 XML 文件很大,SOAP 服务需要很大的带宽。

狭义的专业知识。构建 SOAP API 服务器需要深入了解所涉及的所有协议及其严格限制的规则。

繁琐的消息更新。需要额外的努力来添加或删除消息属性,严格的 SOAP 模式会减慢采用速度。

SOAP 用例

目前,SOAP 体系结构最常用于企业内部或其可信赖的合作伙伴的内部集成。

高度安全的数据传输。SOAP 刚性结构、安全性和授权能力使其成为在 API 和客户端之间执行正式软件合同同时遵守 API 提供者和 API 使用者之间的法律合同的最合适的选择。这就是金融组织和其他企业用户选择 SOAP 的原因。

表征状态转移 (REST):使数据作为资源可用

REST 是一种不言自明的 API 架构风格,由一组架构约束定义,旨在为许多 API 消费者广泛采用。

今天最常见的 API 风格最初是由 Roy Fielding 在 2000 年的博士论文中描述的。REST 使服务器端数据可用简单格式(通常是 JSON 和 XML)来表示它。

REST 的工作原理

REST 没有像 SOAP 那样严格定义。RESTful 架构应该遵守六个架构约束:

  • 统一接口:允许以统一的方式与给定的服务器进行交互,而不管设备或应用程序类型如何
  • stateless:处理请求的必要状态,包含在请求本身中,并且服务器不存储与会话相关的任何内容
  • 缓存
  • 客户端-服务器架构:允许任意一方独立演进
  • 应用分层系统
  • 服务器向客户端提供可执行代码的能力

事实上,有些服务只是在一定程度上是 RESTful 的。它们以 RPC 风格为核心,将较大的服务分解为资源,并有效地使用 HTTP 基础设施。但关键部分是使用超媒体,又名 HATEOAS,是 Hypertext As The Engine of Application State 的缩写。基本上,这意味着对于每个响应,REST API 提供元数据链接到有关如何使用 API 的所有相关信息。这就是使客户端和服务器解耦的原因。因此,API 提供者和 API 消费者都可以独立发展而不会阻碍他们的通信。
Richardson 成熟度模型是实现真正完整和有用的 API 的目标
“HATEOAS 是 REST 的一个关键特性。这真的是让 REST 成为 REST 的原因。由于大多数人不使用 HATEOAS,他们实际上使用的是 HTTP RPC,”这是 Reddit 上表达的一些激进观点。事实上,HATEOAS 是最成熟的 REST 版本。但是,很难实现要求比当今通常使用和构建的 API 客户端更先进、更智能的 API 客户端。所以,即使是今天非常好的 REST API 也并不总是这样做。这就是为什么 HATEOAS 主要作为 RESTful API 设计长期发展的愿景。

当服务实现了 REST 的一些特性和 RPC 的一些特性时,REST 和 RPC 之间确实可能存在一个灰色地带。REST 基于资源或名词,而不是基于动作或动词。
以动词为中心的 RPC 中的操作与以名词为中心的 REST 中的操作相反
在 REST 中,事情是使用 HTTP 方法完成的,例如 GET、POST、PUT、DELETE、OPTIONS,希望还有 PATCH。
Richardson 成熟度模型是实现真正完整和有用的 API 的目标

REST 优点

解耦客户端和服务器。REST 尽可能地解耦客户端和服务器,允许比 RPC 更好的抽象。具有抽象级别的系统能够封装其细节以更好地识别和维持其属性。这使得 REST API 足够灵活,可以随着时间的推移而发展,同时保持稳定的系统。

可发现性。客户端和服务器之间的通信描述了一切,因此不需要外部文档来了解如何与 REST API 交互。

缓存友好。REST 重用了很多 HTTP 工具,是唯一允许在 HTTP 级别缓存数据的样式。相反,任何其他 API 上的缓存实现都需要配置额外的缓存模块。

多种格式支持。支持多种格式来存储和交换数据的能力是 REST 目前成为构建公共 API 的主要选择的原因之一。

REST 缺点

没有单一的 REST 结构。没有完全正确的方法来构建 REST API。如何对资源进行建模以及对哪些资源进行建模将取决于每个场景。这使得 REST 在理论上很简单,但在实践中却很困难。

大有效载荷。REST 返回大量丰富的元数据,因此客户端可以仅从其响应中了解有关应用程序状态的所有必要信息。对于具有大量带宽容量的大型网络管道来说,这种喋喋不休并不是什么大不了的事。但情况并非总是如此。这是 Facebook 在 2012 年提出 GraphQL 风格描述的关键驱动因素。

过度和不足的问题。REST 响应包含的数据过多或不足,通常会​​产生对另一个请求的需求。

REST 用例

管理 API。专注于管理系统中的对象并面向许多消费者的 API 是最常见的 API 类型。REST 帮助此类 API 具有强大的可发现性、良好的文档,并且非常适合此对象模型。

简单的资源驱动应用。REST 是一种很有价值的方法,用于连接不需要灵活查询的资源驱动型应用程序。

GraphQL:只查询需要的数据

它需要多次调用 REST API 才能返回所需的人员。所以 GraphQL 被发明出来是为了改变游戏规则。

GraphQL 是一种描述如何进行精确数据请求的语法。对于具有大量相互引用的复杂实体的应用程序数据模型,实施 GraphQL 是值得的。

如何从 GraphQL 端点仅检索所需的数据
如今,GraphQL 生态系统正在扩展库和强大的工具,如 Apollo、GraphiQL 和 GraphQL Explorer。

GraphQL 的工作原理

GraphQL 从构建模式开始,它描述了您可能在 GraphQL API 中进行的所有查询以及它们返回的所有类型。模式构建很困难,因为它需要模式定义语言 (SDL) 中的强类型。

在查询之前拥有模式,客户端可以验证他们的查询,以确保服务器能够响应它。在到达后端应用程序时,GraphQL 操作将针对整个架构进行解释,并使用前端应用程序的数据进行解析。向服务器发送一个大规模查询,API 返回一个 JSON 响应,其中包含我们所要求的数据的形状。

GraphQL 中的查询执行

除了 RESTful CRUD 操作之外,GraphQL 还具有允许来自服务器的实时通知的订阅。

GraphQL 优点

键入的架构。GraphQL 提前发布了它可以做什么,这提高了它的可发现性。通过将客户端指向 GraphQL API,我们可以找出可用的查询。

非常适合图形数据。深入链接关系但不适合平面数据的数据。

没有版本控制。版本控制的最佳实践是根本不对 API 进行版本控制。

虽然 REST 提供多个 API 版本,但 GraphQL 使用单一的、不断发展的版本,可以持续访问新功能,并有助于更清洁、更可维护的服务器代码。

详细的错误信息。与 SOAP 类似,GraphQL 提供了发生错误的详细信息。其错误消息包括所有解析器,并指代有故障的确切查询部分。

灵活的权限。GraphQL 允许有选择地公开某些函数,同时保留私有信息。同时,REST 架构不会按部分显示数据。要么全有,要么全无。

GraphQL 缺点

性能问题。GraphQL 以复杂性换取其强大功能。一个请求中有太多嵌套字段会导致系统过载。因此,REST 仍然是复杂查询的更好选择。

缓存复杂度。由于 GraphQL 没有重用 HTTP 缓存语义,它需要自定义缓存工作。

大量的前期开发教育。由于没有足够的时间来弄清楚 GraphQL 小众操作和 SDL,许多项目决定遵循众所周知的 REST 路径。

GraphQL 用例

移动 API。在这种情况下,网络性能和单消息负载优化很重要。因此,GraphQL 为移动设备提供了更高效的数据加载。

复杂的系统和微服务。GraphQL 能够在其 API 背后隐藏多系统集成的复杂性。聚合来自多个地方的数据,并将它们合并到一个全局模式中。这对于随着时间的推移而扩展的遗留基础设施或第三方 API 尤其重要。

哪种 API 模式最适合您的用例?

每个 API 项目都有不同的要求和需求。通常,架构选择取决于

  • 使用的编程语言
  • 您正在开发的环境
  • 您必须节省的人力和财力资源

了解每种设计风格的所有权衡后,API 设计人员可以选择最适合项目的一种。

由于其紧密耦合,RPC 适用于内部微服务,但它不是强大的外部 API 或 API 服务的选项。

SOAP 很麻烦,但其丰富的安全功能对于计费操作、预订系统和支付来说仍然是不可替代的。

REST 具有 API 的最高抽象和最佳建模。但它在有线和聊天方面往往更重——如果你在移动设备上工作,这是一个缺点。

GraphQL 在数据获取方面向前迈出了一大步,但并不是每个人都有足够的时间和精力来掌握它。

归根结底,尝试一些具有特定风格的小用例是有意义的,看看它是否适合您的用例并解决您的问题。如果是这样,请尝试扩展并查看它是否适合更多用例。

-- End --