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

gRPC call, channel, connection and HTTP/2 lifecycle

阅读了gRPCCore concepts, architecture and lifecycle, but it doesn't go into the depth I like to see. There is the RPC call, gRPC channel、gRPC连接(文中未描述)和HTTP/2连接(文中未描述)

我很想知道这些是如何组合在一起的。例如,当 RPC 抛出异常时,通道会发生什么情况?通道关闭时 gRPC 连接会发生什么情况?通道什么时候关闭? gRPC 连接何时关闭?心跳?逾期怎么办?

任何人都可以回答这些问题,或者向我指出可以回答的资源吗?

该连接不是 gRPC 概念。它不是正常 API 的一部分,而是一个实现细节。这应该被视为相当正常,就像 HTTP 库提供有关 HTTP 交换的详细信息但不公开连接。

最好将 RPC 和连接视为两个 mostly-separate 系统。

对于不同的“托管”定义,唯一真正的保证是“连接由通道管理”。如果您希望释放连接和其他资源,则必须在不再使用时关闭通道。其他细节要么是实施细节,要么是高级 API 细节。

没有“gRPC 连接”。 “gRPC 连接”只是一个标准的“HTTP/2 连接”。除此之外甚至是许多 gRPC 实现中 transport 的实现细节。这允许有替代的“连接”类型,如“进程中”或 QUIC(通过 Cronet,根本没有经典的“连接”)。

保持所有连接并在必要时重新连接是通道的工作。它将部分责任委托给负载均衡器,负载均衡器 APIs 确实有连接(子通道)的概念。通过不公开与应用程序的连接,负载均衡器有很大的操作自由度。

我会注意到基于 gRPC C-core 的实现跨通道共享连接。

What happens to the channel when a RPC throws an exception?

通道和连接不受 RPC 失败的影响。请注意,connection-level 失败通常会导致 RPC 失败。但是重试之类的事情可能会让 RPC 在新连接上 re-sent。

What happens to the gRPC connection when the channel is closed?

连接最终关闭。通道关闭不是瞬间的,因为现有的 RPC 可以继续,连接关闭也不是瞬间的。但是一旦所有 RPC 完成,连接就会关闭。虽然 C-core 不会关闭连接,直到没有通道正在使用它。

When is the channel closed?

仅当用户关闭它时。

When is the gRPC connection closed?

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

服务器对何时关闭连接有很多发言权。他们可能仅仅因为它们很旧,或者因为它们一直闲置,或者因为服务器过载而关闭它们。但那些只是 use-cases;服务器可以关闭连接 at-will.

What if the deadline is exceeded?

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

我实际上是在等待 Eric 回答这个问题,因为他是这方面的专家!

我也一直在玩 gRPC 一段时间,我想在这里为初学者添加一些东西。有经验的朋友,欢迎编辑!


Channel 是对 long-lived 连接的抽象!客户端应用程序将在启动时创建一个通道。 channel可以在多个线程中reused/shared。这是安全的。对于多线程和多路复用并发请求,一个通道就足够了(对于大多数用例)。关闭/重新连接/保持连接等是通道的责任。我们作为用户通常不必担心这一点。客户端应用程序可以随时关闭通道。创建频道似乎是一个昂贵的过程。所以我们不会对每个 RPC open/close。

当您将 gRPC loadbalancer/nameresolver 用于域名并且名称解析器解析具有多个 IP 地址的域时,通道会创建多个子通道,其中每个子通道都是对与 1 个服务器的连接的抽象。所以一个通道也可以代表多个连接!!

根据 Eric 的评论 添加一些注意事项。

adding the default load balancer still only creates (approximately) one connection if the name resolver returns multiple addresses, as the default is pick_first. But if you change the load balancer to round_robin or virtually any other policy, then yes, there will be multiple connections in a channel. Even if a name resolver returns one address, the load balancer is free to create multiple connections (e.g., for higher throughput), but that's not common today

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

一个通道可以不断地向服务器发送PING帧来保持连接。这些都可以通过频道构建器进行配置。

根据以上信息,如果我们查看您的问题,

当 RPC 抛出异常时通道会发生什么? 频道没有任何反应。服务器上未处理的异常可能会使客户端的 RPC 失败。但通道仍可用于任何 RPC 调用。

通道关闭时 gRPC 连接会发生什么情况? 通道是对连接的抽象。所以它会被关闭。 (同样没有像 Eric 提到的那样的 gRPC 连接。它将是一个 HTTP2 连接)

频道什么时候关闭? 随时都可以。但通常在应用程序关闭时。

gRPC连接什么时候关闭? 这不是我们的问题。频道会处理这个问题。

心跳? 频道定期发送 PING 帧以保持连接。

逾期怎么办? 这有点像客户端的超时。当超过截止日期时,客户端可能会取消请求。频道再次没有任何反应。 (但它可能会在服务器端触发异常,我注意到了几次。(收到未知流的数据帧。https://github.com/grpc/grpc-java/issues/3548)。现在似乎已修复)。