gRPC vs REST:创建API的方法比较

2023年 8月 14日 49.2k 0

译者 | 李睿

审校 | 重楼

本文对gRPC和REST的特征和区别进行了介绍,这可能是当今创建API最常用的两种方法。

以下将从这两种工具的特征开始,也就是它们是什么以及提供什么功能。然后,将根据七个方面对它们进行比较,这对现代系统来说是最重要的7个类别。

其类别如下:

(1)底层HTTP协议

(2)支持的数据格式

(3)数据大小

(4)吞吐量

(5)定义

(6)易于采用

(7)工具支持

gRPC的介绍

当人们听到API时,可能马上想到REST API。然而,REST是构建API的众多方法之一。它并不是适用于所有用例的灵丹妙药。还有其他方法,远程过程调用 (RPC)只是其中之一,而gRPC可能是使用RPC最成功的框架。

尽管gRPC是一种相当成熟和高效的技术,但它仍然被视为一种新技术。因此,尽管在某些用例中非常方便,但它没有REST被广泛采用。

本文主要介绍gRPC,并指出它可以发挥作用的用例。

什么是REST

表述性状态转移(REST)可能是创建公开任何类型API的应用程序的最常用方法。它使用HTTP作为底层通信媒介。正因为如此,它可以从HTTP的所有优点中获益,例如缓存。

  • 客户端-服务器通信
  • 无状态通信
  • 缓存
  • 统一接口
  • 分层系统
  • 按需编码

REST的两个关键概念是:

(1)端点:表示特定资源的唯一统一资源定位符(URL);可以看作是通过互联网访问特定操作或数据元素的一种方式。

(2)资源:在特定URL下可用的特定数据块。

此外,还有一个叫做Richardson成熟模型的描述——这是一个描述REST API中“专业性”程度的模型。它根据特定API具有的特征集将REST API划分为3个级别(或4个级别,取决于是否将级别0计算在内)。

其中一个特征是REST端点应该在URL中使用名词,并使用正确的HTTP请求方法来管理其资源。

  • 示例:用DELETE user/1代替GET user/deleteById/1

至于HTTP方法及其相关操作,如下所示:

  • GET—检索特定的资源或资源集合。
  • POST—创建一个新的资源。
  • PUT—修改整个资源。
  • PATCH -特定资源的部分更新。
  • DELETE—删除指定id的资源。

成熟度模型规定的远不止这些。例如称为HyperMedi的概念。HyperMedia将数据的呈现和对客户端可以执行的操作的控制结合在一起。

对成熟度模型的完整描述超出了本文的范围。

什么是gRPC?

gRPC是远程过程调用(RPC)这个相对古老的概念的另一种实现。谷歌的开发人员创建了它,这就是为什么它的名称里有“g”的原因。它可能是处理RPC最现代和最有效的工具,也是CNCF孵化项目。

gRRC使用谷歌公司的协议缓冲区作为序列化格式,同时利用HTTP/2作为传输介质数据,尽管gRPC也可以使用JSON作为数据层。

  • 方法:gRPC的基本构建块,每个方法都是一个远程过程调用,它接受一些输入并返回输出。它执行用所选编程语言进一步实现的单个操作。目前,gRPC支持4种方法:

①Unary:经典的请求-响应模型,该方法接受输入并返回输出。

②服务器流:该方法接受消息作为输入,同时返回消息流作为输出。gRPC保证了单个RPC调用中的消息排序。

③客户端流:该方法将消息流作为输入,处理它们直到没有消息为止,然后返回一条消息作为输出。与上面类似,gRPC保证在单个RPC调用中进行消息排序。

④双向流:该方法将消息流作为输入,并将消息流作为输出返回,有效地使用了读和写两个消息流。两个流都独立运行,并且将消息顺序保留在流级别上。

  • 服务:表示一组方法,每个方法在服务中必须有其唯一的名称。服务还描述了安全性、超时或重试等特性。
  • 消息:表示方法的输入或输出的对象。

gRPC API定义以.proto文件的形式编写,其中包含上述所有三个基本构建块。此外,gRPC提供了一个协议缓冲区编译器,它从.proto文件生成客户端和服务代码。

用户可以随心所欲地实现服务器端方法,必须坚持使用API的输入输出契约。

在客户端,有一个叫做客户端(或stub)的对象——类似于HTTP客户端。它知道来自服务器的所有方法,只处理调用远程过程并返回它们的响应。

gRPC和REST的比较

(1)底层HTTP协议

这是第一类,可能也是最重要的一类,因为它的影响也可以在其他方面看到。

一般来说,REST是基于请求-响应的,并使用HTTP/1.1作为传输媒介。这里必须使用不同的协议,例如WebSocket或任何类型的流或更持久的连接。

还可以实现一些简单的代码,使REST看起来像消息流。更重要的是,使用HTTP/1.1 REST需要每个请求-响应交换一个连接。对于长时间运行的请求,或者当网络容量有限时,这种方法可能会有问题。

当然,可以使用HTTP/2来构建类似REST的API;然而,并不是所有的服务器和库都支持HTTP/2。因此,其他地方可能会出现问题。

另一方面,gRPC只使用HTTP/2。它允许通过单个TCP连接发送多个请求-响应对。这种方法可以显著地提高应用程序的性能。

  • 结果:gRPC略有获胜

(2)支持的数据格式

假设REST API使用HTTP/1.1的默认情况,那么它可以支持多种格式。

REST通常不对消息格式和样式施加任何限制。基本上,任何一种可以序列化为普通旧文本的格式都是有效的。用户可以在特定场景中使用最适合自己的任何格式。

在REST应用程序中发送数据的最流行格式无疑是JSON。XML排在第二位,因为有大量的较旧/遗留应用程序。

然而,当使用REST和HTTP/2时,只支持二进制交换格式。在这种情况下,可以使用Protobuf或Avro。当然,这种方法也有它的缺点,但在以下几点中会详细说明这一点。

同时,gRPC只支持两种数据交换格式:

①Protobuf —默认情况下。

②JSON—当需要与原有API集成时。

如果用户尝试使用JSON,那么gRPC将使用JSON作为消息的编码格式,而使用GSON作为消息格式。此外,使用JSON需要做更多的配置。

  • 结果:REST获胜,因为它支持更多格式。

(3)数据大小

默认情况下,gRPC使用二进制数据交换格式,这显著地减少了通过网络发送的消息的大小:研究表明,以字节计算,大约减少了40%~50%,而从以前的一个项目中获得的经验表明,甚至减少了50%~70%。

以上提供了JSON和Protobuff之间相对深入的大小比较。本文作者还提供了一个生成JSON和二进制文件的工具。这样就可以重新运行他的实验并比较结果。

本文中的对象相当简单。不过,一般的规则是——嵌入的对象越多,JSON的结构越复杂,它就会比Protobuf更重。50%的大小差异有利于Protobuf 是一个很好的基线。

在使用REST的二进制交换格式时,可以最大限度地减少或消除这种差异。然而,这不是最常见的,也不是最受支持的RESTful API方式,因此可能会出现其他问题。

  • 结果:默认情况下,gRPC获胜;在两者都使用二进制数据格式的情况下,双方为平局。

(4)吞吐量

同样,在REST的情况下,一切都取决于底层HTTP协议和服务器。

在默认情况下,基于HTTP/1.1的REST,即使是最高性能的服务器也无法击败gRPC的性能,特别是当使用JSON时添加序列化和反序列化开销时。虽然当切换到HTTP/2时,差异似乎有所减少。

至于最大吞吐量,在这两种情况下,HTTP都是一种传输媒介,因此它具有无限扩展的潜力。因此,一切都取决于正在使用的工具以及对应用程序的精确操作,因为设计没有限制。

  • 结果:默认情况下为gRPC;在同时使用二进制数据和HTTP/2的情况下,gRPC略胜一筹。

(5)定义

在这一部分中,将描述如何在这两种方法中定义消息和服务。

在大多数REST应用程序中,只是将请求和响应声明为类、对象或特定语言支持的任何结构。然后,依靠提供的库来序列化和反序列化JSON/XML/YAML或任何需要的格式。

此外,目前正在努力创建能够根据Swagger的REST API定义用所选编程语言生成代码的工具。然而,它们似乎是在alpha版本中,所以仍然可能会出现一些错误和小问题,这将使它们难以使用。

REST应用程序的二进制格式和非二进制格式之间几乎没有区别,因为这两种情况下的规则大致相同。对于二进制格式,只是以特定格式所需的方式定义所有内容。

此外,可以通过来自底层库或框架的方法或注释来定义REST服务。该工具还负责将其与其他配置一起向外部世界公开。

在gRPC的情况下,将Protobuf作为默认的并且事实上是编写定义的唯一方式。必须在.proto文件中声明所有内容:消息、服务和方法,所以事情非常简单。

然后使用gRPC提供的工具生成代码,只需要实现自己的方法。在那之后,一切都应该按预期工作。

此外,Protobuf支持导入,因此能够以一种相当简单的方式将设置扩展到多个文件。

  • 结果:在这里没有赢家,给出的描述和建议是,选择最适合自己的方法。

(6)易于采用

在这一部分中,将比较现代编程语言中对每种方法的库/框架支持。

本文作者表示,在他作为软件工程师的职业生涯中,遇到的每种编程语言(Java、Scala、Python)都至少有3个主要的库/框架用于创建类REST应用程序,更不用说将JSON解析为对象/类的库了。

此外,由于REST默认使用人类可读的格式,因此对于新手来说,它更容易调试和使用。这也会影响交付新特性的速度,并帮助用户应对代码中出现的错误。

长话短说,对REST风格应用程序的支持至少非常好。

在Scala中,甚至有一个叫做Tapir的工具。Tapir允许用户抽象HTTP服务器,并编写可用于多个服务器的端点。

gRPC本身为超过8种流行的编程语言提供了客户端库。这通常就足够了,因为这些库包含了制作gRPC API所需的所有内容。此外,一些库为Java(通过Spring Boot Starter)和Scala提供了更高的抽象。

另一件事是,REST如今被认为是一个世界性的标准和构建服务的切入点,而RPC和gRPC,特别是,尽管在这一点上有点过时,但仍然被视为一种新奇事物。

  • 结果:REST被更广泛地采用,并且有更多的库和框架。

(7)工具支持

以上已经介绍了库、框架和一般市场份额,所以在这一部分中介绍围绕这两种风格的工具。它意味着用于测试、性能/压力测试和文档的工具。

①自动化测试

首先,在REST的情况下,用于构建自动化测试的工具被构建到不同的库和框架中,或者是为了这个唯一目的而构建的独立工具,比如REST-assured。

在gRPC的情况下,可以生成一个stub并将其用于测试。如果想要更严格,可以将生成的客户端作为一个单独的应用程序使用,并将其用作对实际服务进行测试的基础。

关于gRPC的外部工具支持,需要知道:

  • Postman程序对gRPC的支持。
  • 在IDE中使用的JetBrains HTTP客户端也可以通过一些最低配置来支持gRPC。
  • 结果一:REST获得胜利。然而,gRPC的情况似乎有所改善。

②性能测试

在这里,REST具有显著的优势,因为像JMeter或Gatling这样的工具使REST API的压力测试变得相当容易。

不幸的是,gRPC没有这样的支持。在当前的Gatling版本中包含了gRPC插件,所以情况似乎正在好转。

然而到目前为止,只有一个名为ghz的非官方插件和库。这些都很好;它只是与REST的支持级别不同。

  • 结果二:REST的胜利;然而,gRPC的情况似乎有所改善。

③文档

在API文档方面,随着OpenAPI和Swagger在整个行业被广泛采用并成为事实上的标准,REST再次取得了胜利。几乎所有用于REST的库都能够以最小的努力或开箱即用的方式公开Swagger文档。

不幸的是,gRPC没有这样的文档。

然而,问题是gRPC是否需要这样的工具。gRPC在设计上比REST更具描述性,因此可能需要其他文档工具。

一般来说,带有API描述的.proto文件比负责编写REST API代码的代码更具声明性和紧凑性,因此可能不需要gRPC提供更多文档。

  • 结果三:REST的胜利。然而,关于gRPC文档的问题是开放的。

④总体结果

这是REST的一次重大胜利。

总结

以下是gRPC和REST比较的最终得分表。

得出的结论是:gRPC和REST的比较结果平分秋色,各有三场胜利,没有明显的赢家。

因此没有什么灵丹妙药,用户只需要考虑哪些类别可能对应用程序最重要,然后选择在大多数类别中获胜的方法。

本文作者表示,如果可以的话,他会尝试使用gRPC,因为gRPC在他的上一个项目中运行得非常好。它可能是比原有的REST更好的选择。

原文标题:gRPC vs REST:Comparing Approaches for Making APIs,作者:Bartłomiej Żyliński

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论