2016-09-22 104 views
9

我使用gRPC与Python作为客户端/服务器内kubernetes荚... 我想能够启动相同类型(gRPC服务器)的多个荚并让客户端连接到他们(随机)。gRPC客户端负载平衡

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

我认为客户端正在做某种DNS缓存,导致所有的呼叫被发送到同一台服务器。是这样吗?是否有禁用它,并设置相同的存根客户端进行“新”呼叫,并通过每个电话通过DNS获取新的IP?

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

编辑

可能不是一个缓存的问题...可能只是GRPC的工作方式。 HTTP/2和持久的可重用连接。任何方式在每次通话后“断开”?

回答

10

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

方式的客户端LB工作在GRPCÇ核心(对于所有的基础,但Java和去香料或GRPC)如下(权威的文档,可以发现here):

客户端LB保持简单和故意“愚蠢”。我们选择实施复杂LB策略的方式是通过外部LB服务器(如上述文档中所述)。你不关心这种情况。相反,您只需创建一个频道,该频道将使用(默认)优先选择 LB策略。

LB策略的输入是已解析地址的列表。在使用DNS时,如果foo.com解析为[10.0.0.1, 10.0.0.2, 10.0.0.3, 10.0.0.4],则策略将尝试建立到所有这些连接的连接。成功连接的第一个将成为选择的,直到它断开。因此名称为“先挑选”。一个更长的名字本来可以是“先选择并尽可能长时间地坚持下去”,但是这个名字是为了一个非常长的文件名:)。如果/当选择的人断开连接时,选择优先策略将移动到返回下一个成功连接的地址(在内部称为“连接的子信道”)(如果有的话)。再一次,只要它保持连接,它将继续选择这个连接的子信道。如果全部失败,通话将失败。

这里的问题是,DNS解析,被固有地基于拉,仅在信道创建触发1)和2)在所选择的连接的子信道的断线。

截至目前,哈克的解决方案是创建为每个请求的新渠道(效率非常低,但它会做给你设置的伎俩)。

在2017年第一季度(见https://github.com/grpc/grpc/issues/7818)来考虑改变将允许客户选择不同的LB政策,即循环赛。另外,我们可能会考虑在该客户端配置中引入一个“随机化”位,这会在对它们执行循环之前对地址进行洗牌,从而有效地实现您的目标。

+0

谢谢你的详细解答。其实,我已经做了,你有什么建议和创建为每个请求(效率不高,我知道)的新渠道。从你的答案我明白,只有在DNS第一个IP会得到请求,直到它停止(没有可用的连接/死亡/坠毁),只有那么客户端将获得第二个IP等等......是吗? – Idan

+0

是的。直到变化使人们有可能首先作为LB政策选择代替挑循环赛,如提及。 –

+0

是否有扩大多台gRPC服务器的典型解决方案?或客户端负载平衡? –

1

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

尝试​​确认您的服务确实知道您的所有后端。

如果您有headless service,则DNS查找将返回带有10个IP(每个Pod一个IP)的A记录。如果您的客户始终选择A记录中的第一个IP,那么这也将解释您所看到的行为。

+0

没有为服务器CLUSTER_IP,我可以看到,我有所有的端点,当我做“GET端点”。仍然到同一台服务器。我认为这可能是gRPC的工作方式和连接重用的HTTP/2 ... – Idan