在 GRPC 上打开频道的最佳做法是什么?

时间:2021-01-18 17:12:24

标签: grpc grpc-java

有些服务通过 GRpc(100+ req/sec)调用服务 A(10 个副本),java 生成的存根。我们没有负载平衡器,但我很好奇这两种情况下的最佳实践是什么。

客户端应该在每次调用服务 A 时构建通道,还是应该创建一次 managedChannel 直到应用关闭?

  1. 如果我为每个请求创建一个,调用会分布在 10 个副本上,但如果我只在应用程序启动时创建,所有调用都会转到同一个服务 A 副本。

  2. 另一方面,如果我在每次调用时创建,在它们空闲(默认为 30 分钟)之前不会打开数千个连接吗?

ManagedChannel managedChannel = ManagedChannelBuilder
                    .forAddress(host, port)
                    .usePlaintext()
                    .build()
ServiceA.newBlockingStub(managedChannel)).fooBar(...)

1 个答案:

答案 0 :(得分:3)

ManagedChannels 应该很少创建和重用。当不再使用 ManagedChannel 时,关闭它是必不可少的。否则会泄漏。

这是一个负载平衡问题,答案取决于您的负载平衡架构。根据您的描述,您可能使用的是以下两种结构之一:

  1. 所有后端都在 DNS 中公开。客户端直接连接到后端。我称之为“暴露”

  2. 有一个 TCP 负载平衡器,客户端创建一个连接到它,平衡器将该连接扩展到后端。我称之为“隐藏”

对于这两种方法,后端设置 nettyServerBuilder.maxConnectionAge(...) 通常是客户端开始使用新后端所必需的。

在暴露的架构中,您只需要在 ManagedChannel 中配置负载均衡。这可能和使用 managedChannelBuilder.defaultLoadBalancingPolicy("round_robin") 一样简单。 round_robin 政策将与 DNS 返回的每个 IP 地址建立连接,并在这些地址之间分发 RPC。当后端因 maxConnectionAge 而断开连接时,客户端将重新解析 DNS 并建立新连接。

在隐藏架构中,如果您有许多客户端,其中每个客户端与每个后端相比都“小”,那么 maxConnectionAge 就足够了。当后端由于 maxConnectionAge 断开连接时,客户端将与负载均衡器建立新连接,负载均衡器可以选择新后端。

在隐藏架构中,如果你有“大”客户端产生的负载超过单个后端可以处理的负载,那么事情就更难了;客户端无法了解后端的数量及其状态,但后端无法自行管理负载。这里最简单的方法是创建多个通道并对其进行循环。在 Java 中,您可以将其实现为 Channel,因此它对您的大部分代码是隐藏的。当后端由于 maxConnectionAge 断开连接时,一个通道将与负载均衡器建立新连接,负载均衡器可以选择一个新后端。这种方法的困难在于知道要制作多少个频道。具有较大客户端的隐藏架构从使用 HTTP 负载平衡而不是 TCP 负载平衡中获益良多。即使使用 HTTP 负载平衡,也可能需要使用多个托管通道,以平衡负载平衡器的负载

相关问题