为什么对gRPC做负载均衡会很棘手?
在过去的几年中,随着微服务的增长,gRPC在这些较小的服务之间的相互通信中获得了很大的普及,在后台,gRPC使用http/2在同一连接和双工流中复用许多请求。
使用具有结构化数据的快速,轻便的二进制协议作为服务之间的通信介质确实很有吸引力,但是使用gRPC时需要考虑一些因素,最重要的是如何处理负载均衡。
gRPC使用粘性连接
gRPC连接是粘性的。这意味着当从客户端到服务器建立连接时,相同的连接将被尽可能长时间地用于许多请求(多路复用)。这样做是为了避免所有最初的时间和资源花费在TCP握手上。因此,当客户端获取与服务器实例的连接时,它将保持连接。
现在,当同一客户端开始发送大量请求时,它们都将转到同一服务器实例。而这正是问题所在,将没有机会将负载分配给其他实例。他们都去同一个实例。
这就是为什么粘性连接会使负载平衡变得非常困难。
以下是一些负载均衡gRPC相互通信的方法,以及每种方法的一些细节。
1.服务器端
当在服务器端完成负载均衡时,会使客户端非常精简,并且完全不知道如何在服务器上处理负载:
网络负载均衡器
网络负载均衡器在OSI (Open Systems Interconnection) 模型的第4层运行。因此,它非常快,可以处理更多的连接。当出现新的TCP通信连接时,负载均衡器将选择一个实例,并且在连接有效期内将连接路由到该单个实例。
现在请记住,gRPC连接是粘性的和持久的,因此它会在负载均衡器后面的客户端和同一服务器实例之间保持相同的连接,只要它可以。
现在这是问题所在:
粘性连接和自动缩放
如果单个服务器实例上的负载(内存或cpu)高于自动伸缩策略,则将导致在该目标组中启动一个新实例。
但是,目标组中的新实例将无济于事。为什么?同样,因为gRPC连接是持久的且具有粘性。正在发送大量请求的客户端,将继续将它们发送到与其连接的同一服务器实例。
因此,新的服务器实例被启动,但是没有请求过载将流向新的实例。利用率高的同一台单服务器实例仍在接收来自客户端的请求负载(因为客户端一直在重用相同的连接)。
自动伸缩策略可能会不断触发并向目标组添加新实例(因为单个实例的cpu /内存过载)。但是这些新实例接收的流量几乎为零。自动缩放策略可能会继续触发并可能最大化目标组中允许的实例,而实际上并未从发送到新实例的请求中受益。
如何使用gRPC粘性连接分配负载?
为了基本上有机会分配负载,我们必须使用以下方法之一放弃粘性和持久连接:
1.客户端定期重新连接
如果您可以控制连接的gRPC客户端,则可以强制客户端定期断开连接并重新连接。此行为将迫使客户端向负载均衡器发送新请求,并且作为对此请求的响应,这次将返回更健康的实例。
2.服务器定期强制断开客户端连接
如果您无法控制连接的gRPC客户端,则可以在服务器端实现类似的逻辑。使服务器在一段时间后强行关闭连接,当它们重新连接时,它会自动使新连接进入更健康的实例。
这些方法中的任何一种都丢失了gRPC的基本优势:可重用的连接。
DNS服务发现
网络负载均衡器的所有问题几乎都适用于DNS服务发现负载均衡。当客户端获取到单个实例的连接时,它将坚持并继续重用它。
2.客户端
如果您完全控制客户端,则可以在客户端实现负载均衡的逻辑。使客户端了解所有可用服务器及其运行状况,并选择要连接的服务器。这将导致客户的逻辑负担增加。因此,它们不仅应包含执行应做的逻辑,而且还需要实现用于负载平衡,运行状况检查等的逻辑。
在一种情况下,这是一个可行的选择:如果您完全控制所有客户端。您不能让有故障的客户端连接到您的服务并导致各种负载平衡问题。只需要一个有故障的客户端就可以引起足够的麻烦。
3. 观察模式
按照官方gRPC负载平衡的建议,此方法使用外部负载均衡器或one-arm负载均衡器在服务器实例之间分配流量。
客户端与外部服务联系,它将返回可用服务器,服务发现和所有其他必需信息的列表。
理想情况下,客户端也会有一些逻辑来帮助做出决定。这种方法很容易出现上面提到的粘性连接问题,因此需要仔细实施。
每个调用都将分别进行负载均衡,而不是每个连接一个,这是理想且理想的情况,它将避免具有沉重的粘性连接。
您需要实现和部署全新的专用服务,以仅负载均衡其他服务之间的gRPC连接。每项新服务都具有自己的维护,操作,监视,警报等。
结论
服务器端负载均衡要有非常重要的考虑,我们无法从gRPC的主要优点之一中受益,后者是粘性可重用连接。
客户端负载均衡需要对客户端进行完全控制,如果有一个错误的客户端,则可能会破坏所有计划。
观察模式负载均衡是对gRPC连接进行负载均衡的最合逻辑且性能最高的解决方案,但是它需要自己的完整且专用的服务,这意味着要在体系结构中实施和操作一项新服务,这些是要考虑到的。
gRPC也需要权衡取舍,了解折衷方案并做出相应选择至关重要。
原文作者: majidfn 原文链接: https://majidfn.com/blog/20201222-grpc-load-balancing/[1]
最后
References
[1]
https://majidfn.com/blog/20201222-grpc-load-balancing/: "https://majidfn.com/blog/20201222-grpc-load-balancing/"