本文讨论了四个主要类型 API 结构风格,比较它们的优缺点,重点介绍每种情况下最合适的 API 架构风格。
两个单独的应用程序需要中介程序来相互通信。因此,开发人员通常需要建立一个桥梁,即应用程序编程界面(API),允许一个系统访问另一个系统的信息或功能。
为了快速、大规模地集成不同的应用程序,API 使用协议或规范来定义通过网络传输的信息的语义和信息。这些规范构成 API 系统结构。
在过去,人们发布了各种不同的产品 API 架构风格。每个架构风格都有它独有的标准化数据交换的模式。这一系列的 API 架构风格的选择引发了很多关于哪种架构风格是最好的争论。

今天,许多 API 的使用者将 REST 被称为消亡 REST”(REST in peace),并且为 GraphQL 感到欢欣鼓舞。十年前,完全是另一个场景:REST 是替代 SOAP 的赢家。这些观点的问题是,它们的出发点只是背书某种技术,而不是考虑它们的实际属性和特性如何匹配当前的需求。
1.RPC:调用另一个系统的函数
远程调用是允许在不同上下文中远程执行函数的一种规范。RPC 扩展本地过程调用的概念,并将其放在 HTTP API 在上下文中。
最初的 XML-RPC 有问题,因为很难保证 XML 有效负载的数据类型。因此,后来 RPC API 开始使用一个更具体的开始 JSON-RPC 该规范被认为是 SOAP 更简单的替代方案。gRPC 是 Google 在 2015 最新年度发展 RPC 版本。gRPC 可插拔支持负载平衡、跟踪、运行状态检查和身份验证,非常适合连接不同的微服务。
RPC 的工作机制
客户端调用远程过程,将参数和附加信息序列化为信息,然后将信息发送到服务端。服务端接到消息后,将信息内容反序列化,执行要求的操作,然后将结果发送回客户端。客户端和服务端负责参数的序列化和反序列化。
RPC 的优势
RPC 使用 GET 获取信息,使用 POST 处理所有其他操作。服务端与客户端之间的交互机制归因于调用端点并获得响应。
如果 API 有了新的需求,我们可以很容易地添加另一个执行需求的端点:1)编写一个新函数并将其放置在一个新端点之后;2)现在,客户可以访问该端点并获取满足其需求的信息。
轻量级有效负载不会对网络产生压力,从而提供高性能,这对于共享服务器和并行计算工作站网络非常重要。RPC 它还可以优化网络层,使每天在不同服务之间发送大量信息非常有效。
RPC 的不足
与底层系统紧密耦合。API 抽象级别有助于其可重用性。API 与基础系统的耦合越紧密,其他系统的可重用性就越差。RPC 与基础系统的紧密耦合不允许其在系统函数和外部 API 之间建立抽象层。这很容易导致安全问题,因为基本系统的细节很容易泄漏 API 中。
RPC 紧密耦合使得可伸缩性要求和松散耦合团队难以实现。因此,客户要么担心特定端点的副作用,要么试图找出要调用的端点,因为客户端不知道服务器如何命名其函数。
可发现性低 RPC 中,无法对 API 检查总结,或发送请求,开始了解根据需要调用哪个函数。
函数爆炸性增长。创建新函数非常容易。因此,与重新编辑现有函数相比,我们倾向于创建新功能,最终产生大量难以理解和重叠的函数。
RPC 的用例
RPC 该模型于20世纪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 就能做到。
2.SOAP:使数据作为服务可用
SOAP 是一个 XML 网络通信协议格式高度标准化。 XML-RPC 发布一年后,SOAP 微软发布并继承了许多 XML-RPC 的特性。在 REST 然后发布,一开始是同时使用的,但很快就发布了 REST 赢得这场比赛已经成为一项更受欢迎的协议。
SOAP 的工作机制
XML 数据格式拖累了大量的数据规范。伴随着大量的新闻结构,XML 使数据格式 SOAP 成为最冗长的 API 架构风格。
SOAP 消息由这些部件组成:
信封标签:用于开始和结束每一条消息
包含请求或响应的文本
标头:用于确认消息是否由某些规范或额外要求确认
故障通知:包括在请求处理过程中只能发生的任何错误
SOAP API 的逻辑由 Web 服务描述语言(WSDL)编写。该 API 描述语言定义了端点,描述了所有可执行的过程。这使得不同的编程语言和 IDE 通信可以快速建立。
SOAP 支持有状态和无状态信息传输。服务器存储在状态下收到的信息可能非常复杂。但这对于涉及多方和复杂交易的操作是合理的。
SOAP 的优势
内置创建 Web 服务功能 SOAP 在发送独立于语言和平台响应的同时,可以处理消息通信。
SOAP 传输协议非常灵活,适用于各种场景。
SOAP API 规范允许带有错误代码和说明的返回 XML 重试消息。
SOAP 与 ES-Security 集成,因此 SOAP 它可以满足企业级的事务要求。它提供隐私和完整性,并允许在新闻级别加密。
SOAP 的不足
如今,由于以下原因,许多开发人员听说必须集成 SOAP API 想法之后会感到不安。
SOAP 消息包含大量元数据,只支持繁琐的请求和响应 XML 格式。
由于 XML 文件的大小,SOAP 服务需要大带宽。
构建 SOAP API 服务器需要深入了解所有涉及的协议及其严格限制。
由于需要额外的工作来添加或删除某个消息属性,这是僵化的 SOAP 该模型减慢了被采用的速度。
SOAP 的用例
目前,SOAP 系统结构最常用于企业内部或与其信任的合作伙伴内部集成。
数据传输高度安全。SOAP 严格的消息结构、安全性和授权功能使其成为 API 最适合与客户端执行正式软件协议的选择,同时也符合要求 API 提供者与 API 用户之间的法律合同。这就是为什么金融机构和其他企业用户选择适用 SOAP 的原因。
3.REST:可以使用数据作为资源
REST 今天是一种无需解释的方式 API 由一系列架构约束定义的架构风格,旨在被广泛定义 API 用户使用。
目前最常见的 API 架构风格最初是由 Roy Fielding 在其博士论文中提出。REST 以简单的格式使服务端数据可用(通常是 JSON 和 XML)来表示它。
REST 的工作机制
REST 的定义并不像 SOAP 那样严格。RESTful 系统结构应遵守以下六种系统结构约束:
无论设备或应用程序类型如何,统一接口:都可以采用统一的方式与给定的服务端进行交互。
无状态:请求本身包含处理该请求所需要的状态,并且服务端不存储与会话相关的任何内容。
缓存
客户端 - 服务器体系结构:允许双方独立发展
应用程序的层级系统
服务端向客户端提供可执行代码的能力
实际上,某些服务仅在某种程度上是 RESTful 的。而它们的内核采用了 RPC 样式,将较大的服务分解为资源,并有效地使用 HTTP 基础结构。但 REST 的关键部分是超媒体(又称 HATEOAS),是超文本作为应用程序状态引擎(Hypertext As The Enginer Of Application State)的缩写。
基本来说,这意味着 REST API 在每个响应中都提供元数据,该元数据链接了有关如何使用该 API 的所有相关信息。这样便可以使客户端和服务端解耦。因此,API 提供者和 API 使用者都可以独立发展,而这并不会阻碍他们的交流。
“HATEOAS 才是 REST 的关键功能,因为它真正使得 REST 成为 REST。但由于大多数人不使用 HATEOAS,因此他们实际上是在使用 HTTP RPC。”这是 Reddit 上表达的一些激进观点。确实,HATEOAS 是 REST 的最成熟版本。
但是,这非常难以实现,因为这要求 API 客户端要比它们如今构建和使用的方式变得更先进和智能得多。因此,即便是如今非常好的 REST API 也不一定总是能做到这一点。这就是为什么 HATEOAS 主要是作为 RESTful API 设计的长期开发的愿景而存在。
当服务端实现 REST 的某些功能和 RPC 的某些功能时,在 REST 和 RPC 之间确实可能存在这样一个灰色区域。但 REST 是基于资源或名词的,而不是基于动作或动词。
在 REST 中,使用例如 GET、POST、PUT、DELETE、OPTIONS 可能还有 PATCH 等 HTTP 方法来完成操作。
REST 的优势
由于 REST 尽可能地解耦了客户端和服务端,REST 相较于 RPC 可以提供更好的抽象性。具有抽象级别的系统能够封装其实现细节,以更好的标示和维持它的属性。这使得 REST API 足够灵活,可以随着时间的推移而发展,同时保持稳定的系统。
客户端和服务端之间的通信描述了所有内容,因此不需要外部文档即可了解如何与 REST API 进行交互。
REST 重用了许多 HTTP 工具,也是唯一一种可以在 HTTP 层面上缓存数据的 API 架构风格。与其相对的是,在任何其他 API 上实现缓存都需要配置其他缓存模块。
REST 拥有支持多种格式用于存储和交换数据的能力,这是它如今成为搭建公共 API 的主要选择的原因之一。
REST 的不足
没有标准的 REST 结构:在构建 REST API 方面,没有具体的正确方法。如何对资源进行建模以及哪些资源需要建模取决于不同的情况。这使得 REST 在理论上很简单,但在实践中却很困难。
庞大的负载:REST 会返回大量丰富的元数据,以便客户端可以仅从响应中了解有关应用程序状态的所有必要信息。对于具有大量带宽容量的大型网络系统来说,这种“啰嗦”的通信并不算很大的负载。但带宽容量并非总是足够的。这也是 Facebook 在 2012 年提出 GraphQL 架构风格的关键驱动因素。
响应过度和响应不足问题。REST 的响应包含的数据会过多或不足,通常会导致客户端需要发送另一个请求。
REST 的用例
在系统中,专注于管理对象并面向许多使用者的 API 是最常见的 API 类型。REST 帮助此类 API 具有强大的可发现性,良好的文档编制,因此 REST 非常适合此对象模型。
在用于连接不需要查询灵活性的资源驱动型应用时,REST 是一种非常有效的方法。
4.GraphQL:仅请求所需要的数据
REST API 需要被多次调用才能返回所需要的资源。所以,GraphQL 被发明了,并改变了这一切游戏的规则。
GraphQL 是一种语法,它描述了如何进行精确的数据请求。有些应用程序的数据模型具有许多相互引用的复杂实体,在这种情况下,实现 GraphQL 是值得的。
如今,GraphQL 的生态系统正在蓬勃发展,出现了例如 Apollo、GraphiQL 和 GraphQL Explorer 等强大的库和工具。
GraphQL 的工作机制
GraphQL 从构建模式(Schema)开始。模式是对于用户可以在 GraphQL API 中进行的所有查询及其返回的所有类型的描述。模式构建非常困难,因为它需要使用模式定义语言(SDL)进行强类型化。
因为在客户端进行查询之前已经定义好了模式,所以客户端可以验证其查询语句,以确保服务端能够对查询语句进行响应。在查询语句到达后端应用程序时,GraphQL 操作将根据整个模式进行解释,并向前端应用程序返回解析到的数据。API 向服务端发送一个庞大的查询,该 API 返回一个仅包含我们所需数据的 JSON 响应。
除了包含 RESTful 的 CRUD 操作,GraphQL 还有订阅(subscriptions)机制,允许接收来自服务端的实时通知。
GraphQL 的优势
GraphQL 提前公开了它能做什么,从而提高了其可发现性。通过将客户端指向 GraphQL API,我们可以发现什么查询语句是可用的。
版本控制的最佳实践是不要对 API 进行版本控制。
尽管 REST 提供了不同的 API 版本,GraphQL 使用的是不断更新的单一版本,这使用户可以持续访问新功能,并有助于提供更整洁、更可维护的服务器代码。
GraphQL 以类似于 SOAP 的方式提供所发生错误的详细信息。它的错误消息包括所有解析器,并指向确切的发生故障时的查询部分。
GraphQL 允许选择性地公开某些功能,同时保留私人信息。而相对应的是,REST 体系架构不能仅显示部分数据,要么是全部数据,要么是没有数据。
GraphQL 的不足
GraphQL 权衡了复杂性,来实现其强大功能。一个请求中的嵌套字段太多会导致系统过载。因此,对于复杂的查询,REST 仍然是更好的选择。
由于 GraphQL 不再使用 HTTP 缓存语义,因此使用者需要额外自定义缓存。
由于没有足够的时间来了解 GraphQL 的某个操作和 SDL,因此许多项目决定采用众所周知的 REST 方法。
GraphQL 的用例
在这种情况下,网络性能和单个消息有效负载优化很重要。因此,GraphQL 为移动设备提供了更有效的数据加载方式。
GraphQL 能够隐藏其 API 背后的多个系统集成的复杂性。GraphQL 从多个地方聚合数据,并将它们合并为一个全局的模式。对于随时间推移而逐渐扩展的遗留基础架构或第三方 API 来说,这尤其重要。
5.哪种 API 模式最适用你的用例?
每个 API 项目都有不同的限制和需求。通常,API 架构的选择取决于:
所使用的编程语言,
你的开发环境,以及
你的资源预算,包括人力资源和财务资源。
在了解了每种设计风格的利与弊之后,API 设计人员可以选择最适合项目的那一种。
具有强耦合性的 RPC 很适用于内部微服务,但它对外部 API 或者 API 服务而言不是一个好的选择。
SOAP 的使用有些麻烦,但它强大的安全拓展使它在计费操作、预订系统和支付方面是无可替代的。
REST 是针对 API 的最高级别的抽象和最佳模型。但它往往会有些“啰嗦”而增加系统的负担 —— 如果你使用的是移动设备,这是个问题。
GraphQL 在数据获取方面向前迈出了一大步,但并不是每个人都有足够的时间后精力来掌握它。
归根结底,去针对一些小型的用例来尝试某种特定 API 架构,并去了解它是否适合你的用例以及是否解决了你的问题,这样做是比较合适的。如果它适用于你的用例,就可以尝试扩展并查看它是否适用于更多的用例。
来源:infoQ
主流Java进阶技术(学习资料分享)
PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下,加个,这样每次新文章推送才会第一时间出现在你的订阅列表里。点支持我们吧!