gRPC调用、通道、连接和HTTP/2生命周期

19

我阅读了 gRPC 的核心概念、架构和生命周期,但它没有深入探讨我想看到的内容。其中包括RPC 调用gRPC 通道、gRPC 连接(文章中未描述)以及 HTTP/2 连接(文章中未描述)。

我想知道这些内容是如何结合在一起的。例如,当 RPC 抛出异常时,通道会发生什么?当通道关闭时,gRPC 连接会发生什么?通道何时关闭?gRPC 连接何时关闭?心跳?如果超过截止时间怎么办?

有人可以回答这些问题,或者指导我可以查看哪些资源吗?


1
完全同意,这方面确实没有详细的文档说明。 - abhilash_goyal
2个回答

29
连接并不是gRPC的概念,它不是普通API的一部分,而是实现细节。这应该被视为相当正常的情况,就像HTTP库提供有关HTTP交换的详细信息但不公开连接一样。
最好将RPC和连接视为两个大部分独立的系统。
唯一的真正保证是“连接由通道管理”,对于“管理”的不同定义来说。如果您希望释放连接和其他资源,则必须在不再使用时关闭通道。其他细节要么是实现细节,要么是高级API细节。
没有“gRPC连接”。 “gRPC连接”只是一个标准的“HTTP/2连接”。除了这在许多gRPC实现中甚至是传输的实现细节。这使得可以拥有替代“连接”类型,例如“进程内”或QUIC(通过Cronet,在那里根本没有经典的“连接”)。
保持所有连接并根据需要重新连接是通道的工作。它将一部分责任委托给负载均衡器和负载均衡API确实有连接(子通道)的概念。通过不向应用程序公开连接,负载均衡器可以非常自由地操作。
我要注意的是,基于gRPC C核心的实现共享跨通道的连接。

当一个RPC抛出异常时,通道会发生什么?

通道和连接不会受到失败的RPC的影响。请注意,连接级别的故障通常会导致RPC失败。但是,例如重试可以允许在新连接上重新发送RPC。

当通道关闭时,gRPC连接会发生什么?

连接最终会被关闭。通道关闭并非瞬间完成,因为现有的RPC可能会继续执行,并且连接关闭也不是瞬间完成。但是,一旦所有RPC完成,连接就会关闭。尽管C-core不会关闭连接,直到没有通道再使用它为止。

什么时候会关闭通道?

仅当用户关闭它时。

什么时候会关闭gRPC连接?

很多时候。客户端可能在不再需要时关闭连接。例如,假设服务器IP地址发生更改,客户端需要连接到1.1.1.2而不是1.1.1.1。将创建一个新的连接,并且新的RPC将转到新的IP地址。客户端还可以关闭其认为已经死亡的连接(例如,通过keepalive超时)。

服务器有很多决定何时关闭连接的方式。他们可能会简单地关闭它们,因为它们过时了,或者因为它们已经闲置,或者因为服务器过载了。但这些只是使用案例;服务器可以随时关闭连接。

如果超过了截止日期会怎样?

截止日期仅适用于RPC,不影响通道或连接。


27
我实际上在等待专家Eric回答这个问题!我也一直在使用gRPC进行开发,想为初学者们添加一些内容。有经验的用户可以随时编辑!通道是一个长连接的抽象层!客户端应用程序将在启动时创建通道。通道可以在多个线程之间重复使用/共享。它是线程安全的。一个通道足够(对于大多数用例)多个线程和多路复用并发请求。关闭/重新连接/保持连接活动等都是通道的责任。一般情况下,作为用户,我们不必担心这些问题。客户端应用程序随时可以关闭通道。创建通道似乎是一个昂贵的过程。因此,我们不会为每个RPC打开/关闭通道。 当您使用gRPC负载均衡器/名称解析器来处理域名并且名称解析器使用多个IP地址解析该域名时,通道会创建多个子通道,其中每个子通道都是与1个服务器的连接的抽象层。因此,一个通道还可以表示多个连接!根据Eric的评论,还要注意以下几点。添加默认负载均衡器仍然只创建(大约)一个连接,如果名称解析器返回多个地址,则默认选择选择第一个。但是,如果将负载平衡器更改为如果使用round_robin或其他任何策略,那么通道中将会有多个连接。即使名称解析器返回一个地址,负载均衡器也可以自由地创建多个连接(例如为了更高的吞吐量),但这在今天并不常见。

基础连接随时可能因任何原因而关闭。例如:远程服务器定期进行计划维护,或连接长时间处于空闲状态。在这种情况下,服务器可以向客户端发送GOAWAY信号,客户端可能会断开并重新连接到其他服务器,或者服务器可能因OOM错误而崩溃。在这种情况下,通道将检测到连接失败,并为其他服务器重试新的连接等。

通道可以持续向服务器发送PING帧以保持连接活动状态。所有这些都可以通过通道构建器进行配置。

根据上述信息,如果我们看一下你的问题:

当RPC引发异常时,通道会发生什么? 通道不会发生任何变化。服务器上未处理的异常可能会使客户端的RPC失败。但通道仍可用于任何RPC调用。

当通道关闭时,gRPC连接会发生什么? 通道是连接的抽象层,因此它将关闭。(再次说明,没有所谓的gRPC连接,正如Eric所提到的那样。它将是一个HTTP2连接)

何时关闭通道? 您可以随时关闭,但通常在应用程序关闭时关闭。

gRPC连接何时关闭? 这不是我们的问题。通道会处理这个问题。

心跳? 通道会定期发送PING帧以保持连接活动状态。

如果超过截止日期怎么办? 这类似于客户端的超时。当截止日期超过时,客户端可能会取消请求。再次强调,通道没有任何变化。(但这可能会在服务器端触发异常,我曾经注意到几次。 收到未知流的数据帧。https://github.com/grpc/grpc-java/issues/3548)。现在看来已经解决了。


1
非常感谢。 - abhilash_goyal
3
这非常准确。尽管从技术上讲,默认的负载均衡器仍然只会创建(大约)一个连接,如果名称解析器返回多个地址,则默认为“pick_first”。但是,如果您将负载均衡器更改为“round_robin”或几乎任何其他策略,那么在通道中将有多个连接。即使名称解析器返回一个地址,负载均衡器也可以自由地创建多个连接(例如,为了实现更高的吞吐量),但这在今天并不常见。 - Eric Anderson
我正在处理grpc-js,我想知道为什么Channel的连接状态可以是ready,即使subchannel状态仍然是idle。Channel状态和subchannel状态之间有什么关系?或者说,即使唯一的subchannel仍处于空闲状态,Channel状态如何能够准备就绪? - CMCDragonkai
通道会定期发送PING帧以保持连接活动状态。你确定吗?!默认情况下,KeepAliveTime是永久的(因此关闭),keepAliveWithoutCalls也关闭。只有idleTimeout开启(30分钟)。因此我怀疑默认情况下没有ping。 - Simon Logic
@SimonLogic他并没有建议默认发送保持连接的ping。 - Rahul Sharma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接