REST 与 gRPC:我啥时候应该选择其中之一?

Posted

技术标签:

【中文标题】REST 与 gRPC:我啥时候应该选择其中之一?【英文标题】:REST vs gRPC: when should I choose one over the other?REST 与 gRPC:我什么时候应该选择其中之一? 【发布时间】:2018-01-19 10:07:06 【问题描述】:

我看到越来越多的软件组织在其面向服务的架构中使用 gRPC,但人们也仍在使用 REST。在哪些用例中使用 gRPC 有意义,何时使用 REST 进行服务间通信有意义?

有趣的是,我遇到过同时使用 REST 和 gRPC 的开源项目。例如,Kubernetes 和 Docker Swarm 都在一定程度上使用 gRPC 进行集群协调,但也公开了 REST API 用于与主/领导节点的接口。为什么不上下使用 gRPC?

【问题讨论】:

附言。我应该澄清一下,我并不期待一个真实的、大部分正确的答案,而是围绕开发人员在处理这些技术选择方面的经验进行讨论。 【参考方案1】:

如果操作正确,REST 会提高长期的可演化性和可扩展性,但会牺牲性能并增加复杂性。 REST 非常适合必须独立开发和维护的服务,例如 Web 本身。客户端和服务器可以松散耦合并在不相互破坏的情况下进行更改。

以灵活性和独立性为代价,RPC 服务可以更简单,性能更好。 RPC 服务非常适合客户端和服务器紧密耦合并遵循相同开发周期的情况。

但是,大多数所谓的 REST 服务根本不遵循 REST,因为 REST 只是任何类型的 HTTP API 的流行词。事实上,大多数所谓的 REST API 都是紧密耦合的,它们与 RPC 设计相比没有任何优势。

鉴于此,我对您的问题有点愤世嫉俗的回答是:

    有些人采用 gRPC 的原因与他们几年前采用 REST 的原因相同:按流行词设计。

    很多人都意识到他们实现 REST 的方式无论如何都相当于 RPC,那么为什么不使用标准化的 RPC 框架并正确实现它,而不是坚持糟糕的 REST 实现呢?

    REST 是一种解决方案,用于解决跨多个组织并具有长期目标的项目中出现的问题。也许人们意识到他们并不真正需要 REST 并寻找更好的选择。

【讨论】:

虽然我同意你的大部分陈述,但 gRPC 可以 与 reflection 等结构一起使用,它允许客户端发现服务,因此在此提供相同的功能上下文作为真正的 RESTful API。在微服务架构中使用这个 + 服务发现(例如 Consul)可以为您的服务提供公平的灵活性和独立性。 Client and server can be loosely coupled and change without breaking each other. 你能解释一下吗,为什么这在 gRPC 中是不可能的,最好用一个简单的例子。抱歉问了这么愚蠢的问题。 @wonder 我说的是一般的 RPC 框架,而不是具体的 gRPC。完全有可能,关键是您将在设计决策上浪费多少时间和精力,如果您使用更好的框架来完成手头的工作,这无关紧要。 @pedro 由于像 gRPC 这样的 RPC 使用 protobuff ,所以基本上我们需要在服务器和客户端(App)上都有 .proto ,而在 Rest 我们可以在服务器(GSON)上使用不同的 JSON 解析器和客户(杰克逊)方面。我以为您指的是这种差异。如果这似乎是错误的,请指正。【参考方案2】:

根据 gRPC 的 future roadmap,人们将继续迁移到它并让 REST(通过 HTTP)“安静”。

gRPC 在很多方面更方便

通常很快(比如超快) (几乎)没有“设计二分法”——什么是正确的端点,什么是正确的 HTTP 动词,等等。 不处理 混乱 输入/响应序列化,因为 gRPC 处理序列化 ― 更高效的数据编码和 HTTP/2,通过单个连接和标头压缩的多路复用请求使事情变得更快 定义/声明您的输入/响应并为不同语言生成可靠的客户端(当然,“支持”的客户端,这是一个巨大的优势) 形式化的错误集 - 这是有争议的,但到目前为止,它们比 HTTP 状态代码更直接地适用于 API 用例

在任何情况下,您都必须处理所有 gRPC 麻烦,因为这个世界上没有什么是绝对可靠的,但到目前为止,它“看起来比 REST 更好”——并且实际上已经证明了这一点。

我认为你可以两全其美。在任何情况下,gRPC 都在很大程度上遵循 HTTP 语义(通过 HTTP/2),但明确允许全双工流式传输,与典型的 REST 约定不同,因为它在调用调度期间出于性能原因使用 静态路径 作为解析调用参数从路径 ― 查询参数和有效负载正文增加了延迟和复杂性。

【讨论】:

【参考方案3】:

REST 的承诺一直是uniform interface。理想的 REST 客户端应该能够与各种 RESTful 资源进行通信,即使是那些在客户端编写代码时不存在的资源。

不幸的是,除了 REST 的原始案例——人类可读文档的万维网之外,这个理想从未真正实现。

此时,大多数自称为“RESTful”的接口实际上是一种巴洛克式的 RPC,其中请求和响应数据被涂抹在方法、查询字符串、标头、状态码、有效负载上,所有这些都以各种脆弱的格式.

当今“RESTful”接口的大部分一致性都在开发人员的头脑中。他们“知道”POST /orders/ 可能会添加新订单。但是他们仍然必须对他们的客户进行编程以“知道”,对于他们与之交谈的每个 API,经常会犯很多错误。

不过,仍有一些一致性在代码中实际上是有用的。例如,如果你有一个“RESTful”API,那么你通常可以几乎免费地向它添加一个透明的、可微调的缓存层。这是可能的,因为(语义正确)HTTP 消息已经携带了缓存所需的所有标准化信息:请求方法、URL、状态码、Cache-ControlVary 等等。在 gRPC 中,您必须滚动自己的缓存。

但“REST”目前占据主导地位的真正原因并不是这种次要的可供性。这真的只是万维网的成功。在历史的某个时刻,每个人已经拥有一个高性能、灵活的 HTTP 服务器(为他们的网站提供服务)和一个可靠的 HTTP 客户端(用于查看所述站点),所以当人们开始添加机器时- 可读资源,坚持使用相同的 HTTP 方式更容易、更便宜。他们使用 HTTP 方法、标头和状态代码,因为这是他们的 Web 服务器已经理解和记录的内容。 php 之类的工具使他们能够在常规网站上实现零部署开销。

如果一致性和与万维网的一致性对您来说并不重要,那么 RPC 是一种经过验证的真正架构选择,而 gRPC 是一种可靠的实现,可以为您省去一些麻烦,正如 ɐuıɥɔɐɯ 解释的那样。

【讨论】:

以上是关于REST 与 gRPC:我啥时候应该选择其中之一?的主要内容,如果未能解决你的问题,请参考以下文章

我啥时候应该选择 SAX 而不是 StAX?

Android 的 Html.escapeHtml 和 TextUtils.htmlEncode 有啥区别?我啥时候应该使用其中一种?

Android 的 Html.escapeHtml 和 TextUtils.htmlEncode 有啥区别?我啥时候应该使用其中一种?

基于场景选择微服务的API范式:RESTGraphQLWebhooks和gRPC

Node.js - 我啥时候应该做异步的事情,啥时候做同步

带有REST和Open API的gRPC