gRPC客户端负载平衡

2024-06-12 23:31:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用gRPC和Python作为kubernetes pods中的客户机/服务器。。。 我希望能够启动同一类型的多个pod(gRPC服务器),并让客户端连接到它们(随机)。

我发送了10个服务器的pod,并设置了一个“服务”来瞄准它们。然后,在客户机中,我连接到服务的DNS名称-这意味着kubernetes应该进行负载平衡,并将我定向到随机服务器pod。 实际上,客户机调用gRPC函数(运行良好),但是当我查看日志时,我发现所有调用都指向同一个服务器pod。

我假设客户端正在进行某种DNS缓存,这会导致所有调用都发送到同一个服务器。是这样吗?是否仍有禁用它并设置相同的存根客户端来进行“新”调用,并在每次调用时通过DNS获取新的ip?

我知道如果它每次都查询DNS服务器,可能会导致开销,但此时对我来说,分配负载更为重要。


Tags: 函数ip服务器名称客户端类型grpc客户机
3条回答

如果您已经创建了vanilla Kubernetes服务,那么该服务应该有自己的负载平衡虚拟IP(检查kubectl get svc your-service是否显示服务的CLUSTER-IP)。如果是这种情况,DNS缓存不应该是一个问题,因为单个虚拟IP应该在实际后端之间分割流量。

尝试kubectl get endpoints your-service确认您的服务实际上知道您的所有后端。

如果您有一个headless service,DNS查找将返回一个具有10个ip的a记录(每个pod一个)。如果你的客户总是选择A记录中的第一个IP,这也可以解释你看到的行为。

通常的K8S负载平衡对gRPC不起作用。下面的链接解释了原因。 https://kubernetes.io/blog/2018/11/07/grpc-load-balancing-on-kubernetes-without-tears/

This is because gRPC is built on HTTP/2, and HTTP/2 is designed to have a single long-lived TCP connection, across which all requests are multiplexed—meaning multiple requests can be active on the same connection at any point in time. Normally, this is great, as it reduces the overhead of connection management. However, it also means that (as you might imagine) connection-level balancing isn’t very useful. Once the connection is established, there’s no more balancing to be done. All requests will get pinned to a single destination pod.

大多数现代的入口控制器都可以处理这个问题,但它们要么是热烘箱(nginx),要么是alpha版本(traefik),要么需要最新版本的K8S(Linkerd)。您可以进行客户端负载平衡,其中可以找到Java解决方案here

让我借此机会通过描述事情应该如何工作来回答。

客户端LB在GRPC C内核中工作的方式(所有的基础,除了java和GO滋味或GRPC)如下(权威文档可以找到{a1}):

客户端LB保持简单,并且故意“哑”。我们选择的实现复杂LB策略的方法是通过外部LB服务器(如前面的文档所述)。你不关心这个场景。相反,您只需创建一个通道,它将使用(默认值)pick firstLB策略。

LB策略的输入是已解析地址的列表。使用DNS时,如果foo.com解析为[10.0.0.1, 10.0.0.2, 10.0.0.3, 10.0.0.4],则策略将尝试建立到所有这些服务器的连接。第一个成功连接的将成为所选的,直到它断开。因此就有了“先挑”这个名字。一个较长的名字可以是“先选择并尽可能长时间地坚持”,但这就形成了一个很长的文件名:)。如果/当所选的一个被断开时,pick first策略将移到返回下一个成功连接的地址(内部称为“连接的子信道”),如果有的话。再次,只要保持连接,它将继续选择此已连接的子频道。如果他们都失败了,电话就会失败。

这里的问题是,DNS解析本质上是基于拉的,仅在1)通道创建时触发,2)在所选连接的子通道断开时触发。

到目前为止,一个棘手的解决方案是为每个请求创建一个新的通道(非常低效,但它会按照您的设置完成任务)。

鉴于2017年第一季度的变化(见https://github.com/grpc/grpc/issues/7818),客户可以选择不同的LB策略,即循环。此外,我们可能会考虑在客户机配置中引入一个“随机化”位,这将在对地址进行循环之前对地址进行洗牌,从而有效地实现您的意图。

相关问题 更多 >