gRPC vs REST:两种API架构风格的对比
API,即应用程序编程接口。这些接口充当软件中介,为应用程序之间的交互和对话建立特定的定义和规则。API 负责将响应从用户传递到系统,然后从系统返回给用户。听起来还是有点糊涂?
API 的工作机制
假设我们正在预订一个酒店。我们在笔记本电脑上访问酒店预订页面,连接到互联网的这个页面会将数据(我们的请求)发送到服务器。然后,服务器检索数据,解析它,一旦所需的操作得到执行,它就会向我们发送一个响应,并在我们的界面上提供信息。这个过程需要 API 才能实现。
API 指定了一个应用程序(网页或移动应用)可以向另一个应用程序发出的请求类型,并进一步确定:如何发出这些请求;使用哪些数据格式;以及用户必须遵循的实践。
本文会对比 gRPC 和 REST 两大架构风格,因为它们代表了人们创建 API 时最常用的两种架构风格。
一方面,在单体应用程序中,项目的所有功能都包含在一个单元中,更准确地说是包含在一个代码库中。另一方面,微服务架构由一些较小的服务组成,这些服务使用 HTTP 等协议相互通信。作为微服务架构一部分的组件服务通过 API 相互通信和交互。换句话说,API 允许集成到微服务应用程序中的所有服务互相连接和通信。
最常用的架构风格是 REST API。但构建 API 时主要有 3 种模型:RPC(远程过程调用)、REST(表征状态传输)和 GraphQL。在本文中,我们将重点介绍前两个。
RPC 使用客户端 - 服务器模型。请求服务器(换句话说就是客户端)请求一条消息,该消息由 RPC 转换并发送到另一台服务器。服务器收到请求后将响应发送回客户端。当服务器处理这个调用时,客户端被阻塞,服务器内部的消息传递被隐藏。
此外,RPC 允许客户端以特定格式请求函数,并以完全相同的格式接收响应。在 URL 中可以找到使用 RPC API 提交调用的方法。RPC 支持本地和分布式环境中的远程过程调用。
与 REST API 一样,RPC 还建立了交互规则以及用户如何提交“调用”(请求)以调用方法与服务通信和交互的机制。
使用 REST API 时,来自后端数据的响应通过 JSON 或 XML 消息格式传递给客户端(或用户)。这种架构模型倾向于遵循 HTTP 协议。然而,在维护 RCP 模型的同时,RCP 设计也时常从 HTTP 中汲取一些想法。事实上,不管使用的是哪种模型(RPC 或 REST),大多数现代 API 实现都将 API 映射到相同的 HTTP 协议时。
当 REST API 公开可用时,每个集成微服务应用程序的服务都可以作为资源呈现给用户 / 客户端,资源可以通过以下 HTTP 命令访问:GET
、DELETE
、POST
和PUT
。
gRPC 是 Google Remote Procedure Call 的简写,是基于 RCP 架构的变体。该技术遵循一个使用 HTTP 2.0 协议的 RPC API 实现,但 HTTP 不会呈现给 API 开发人员或服务器。因此,开发人员无需担心 RPC 概念如何映射到 HTTP,从而降低了复杂性。
总的来说,gRPC 旨在加快微服务之间的数据传输。它的基础方法是确定一个服务,建立方法和相应的参数来实现远程调用和返回类型。
此外,它以 一个 IDL(接口描述语言)表示 RPC API 模型,这为确定远程过程提供了更直接的方法。默认情况下,IDL 使用 Protocol Buffers(但也可以使用其他替代方案)来描述服务接口以及负载消息的结构。
现在,我们对 gRPC 和 REST 有了一个初步认识,下面我们来看看它们的主要区别。
REST API 遵循一个通常基于 HTTP 1.1 构建的 请求 - 响应通信模型。不幸的是,这意味着如果一个微服务收到来自多个客户端的多个请求,该模型必须每次只处理一个请求,拖慢了整个系统的速度。REST API 也可以构建在 HTTP 2 上,但通信的请求 - 响应模型保持不变,这使得 REST API 无法充分利用 HTTP 2 的优势,例如 流式通信 和 双向支持。
gRPC 没有面临类似的障碍。它建立在 HTTP 2 之上,且遵循客户端 - 响应通信模型。这让它支持双向通信和流式通信,因为 gRPC 能接收来自多个客户端的多个请求,并通过不断地流式传输信息来同时处理这些请求。此外,gRPC 还可以处理“一元”交互,例如构建在 HTTP 1.1 上的交互。
总之,gRPC 能处理一元交互和多种类型的流:
一元:客户端发出单个请求并接收单个响应。
服务器流:服务器对客户端的请求响应一个消息流。当全部数据发送完毕后,服务器会再发送一条状态消息来完成流程。
客户端流:客户端向服务器发送一个消息流,并接收单个响应消息。
双向流:客户端和服务器的两个流互相独立,也就是说它们都能以任何顺序传输消息。客户端负责发起并结束双向流。
流类型
这可能是 REST 相对于 gRPC 的主要优势之一。一方面,所有浏览器都完全支持 REST。另一方面,gRPC 获得的浏览器支持仍然非常有限。
不幸的是,它需要 gRPC-web 和一个代理层来执行 HTTP 1.1 和 HTTP 2 之间的转换。因此,gRPC 主要用于内部 / 私有系统(特定组织的后端数据和应用程序功能中的 API 程序)。
如前所述,gRPC 默认使用 Protocol Buffers 来序列化负载数据。这个方案更轻便,因为它支持高度压缩的格式并减少了消息的大小。此外,Protobuf(或 Protocol Buffer)是二进制的;它对结构化数据进行序列化和反序列化,以便通信和传输。换句话说,强类型消息可以自动从 Protobuf 转换为客户端和服务器的编程语言。
相比之下,REST 主要依靠 JSON 或 XML 格式来发送和接收数据。事实上,即使它不强制要求任何结构,JSON 也是最流行的格式,因为它具有灵活性和发送动态数据的能力,而不必遵循严格的结构。使用 JSON 的另一显著优势是其人类可读水平,这方面 Protobuf 尚无法与之竞争。
尽管如此,JSON 在数据传输方面并不够轻量或快速。其原因在于,在使用 REST 时,必须将 JSON(或其他格式)序列化并转换为客户端和服务器端使用的编程语言。这在传输数据的过程中增加了一个额外步骤,从而可能会损害性能并增加出现错误的可能性。
与 gRPC 不同,REST API 不提供内置代码生成功能,这意味着开发人员必须使用 Swagger 或 Postman 等第三方工具为 API 请求生成代码。
相比之下,gRPC 由于其 protoc 编译器而具有原生代码生成功能,该编译器与多种编程语言兼容。这对于集成了以不同语言和平台开发的各种服务的微服务系统来说尤其方便。此外,内置的代码生成器还有助于创建 SDK(软件开发工具包)。
如前所述,尽管 gRPC 提供了许多优势,但它有一个主要障碍:浏览器兼容性低。因此,gRPC 的用例一般局限在内部 / 私有系统。
相比之下,正如我们所讨论的那样,REST API 可能有其缺点,但它们仍然是连接基于微服务的系统的最流行的 API。此外,REST 遵循 HTTP 协议标准化并提供通用支持,使这种 API 架构风格成为 Web 服务开发以及应用程序和微服务集成的首选。然而,这并不意味着我们应该忽视 gRPC 的应用场景。
gRPC 架构风格具有很多值得(并且应该)探索的有前途的特性。它是处理多语言系统和实时流的绝佳选择,例如,当运营需要轻量级消息传输(可以由序列化 Protobuf 消息支持)的 IoT 系统时,gRPC 就很合适。此外,gRPC 也可以考虑用于移动应用程序,因为它们不需要浏览器,且消息体积更小,不会拖慢移动设备的速度。
gRPC 提供了很多优势。与 REST 不同,它可以充分利用 HTTP 2,使用多路复用流并遵循二进制协议。此外,由于 Protobuf 消息结构,它还具备性能优势,支持多语言环境的内置代码生成功能也是一大好处。这些因素使 gRPC 成为了一种很有前途的 API 架构风格。
尽管如此,浏览器支持不足使 gRPC 很难匹敌 REST 的通用支持能力。REST 仍然是微服务系统中的粘合剂,是最流行的解决方案。因此它很可能会存在很长时间,而且说实话,它是一个非常成熟和成功的架构。