Ida*_*dan 17 python dns http kubernetes grpc
我正在使用gRPC和Python作为kubernetes pods中的客户端/服务器......我希望能够启动多个相同类型的pod(gRPC服务器)并让客户端(随机)连接它们.
我发送了10个服务器的pod并设置了一个"服务"来定位它们.然后,在客户端,我连接到服务的DNS名称 - 意味着kubernetes应该进行负载平衡并将我引导到随机服务器pod.实际上,客户端调用gRPC函数(效果很好)但是当我查看日志时,我看到所有调用都转到同一个服务器pod.
我假设客户端正在进行某种DNS缓存,这导致所有调用都被发送到同一服务器.是这样的吗?无论如何要禁用它并设置相同的存根客户端进行"新"呼叫并通过DNS每次呼叫获取新的IP?
我知道如果它每次都会查询DNS服务器,我可能会产生的开销,但是分配负载对我来说更重要.
编辑
可能不是缓存问题......可能只是gRPC的工作方式.HTTP/2和持久可重用连接.每次通话后有什么方法可以"断开"?
Dav*_*tas 18
让我借此机会通过描述事情应如何运作来回答.
客户端LB在gRPC C核心(除了Java和Go版本或gRPC之外的所有基础)的工作方式如下(权威文档可以在这里找到):
客户端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)在所选连接子信道断开时触发.
到目前为止,一个hacky解决方案是为每个请求创建一个新的通道(非常低效,但它可以根据您的设置进行操作).
鉴于2017年第一季度的变化(请参阅https://github.com/grpc/grpc/issues/7818)将允许客户选择不同的LB策略,即Round Robin.此外,我们可能会考虑向该客户端配置引入一个"随机化"位,这将在对其进行循环操作之前对地址进行洗牌,从而有效地实现您的意图.
通常的 K8S 负载平衡不适用于 gRPC。以下链接解释了原因。 https://kubernetes.io/blog/2018/11/07/grpc-load-balancing-on-kubernetes-without-tears/
这是因为 gRPC 是建立在 HTTP/2 之上的,而 HTTP/2 被设计为具有一个长期存在的 TCP 连接,所有请求都通过该连接进行多路复用——这意味着多个请求可以在任何时间点在同一连接上处于活动状态。通常,这很好,因为它减少了连接管理的开销。但是,这也意味着(如您所想)连接级平衡不是很有用。一旦建立了连接,就不需要再进行平衡了。所有请求都将固定到单个目标 Pod。
大多数现代入口控制器都可以处理这个问题,但它们要么是炙手可热的 (nginx),要么是 alpha 版本 (traefik),或者需要最新版本的 K8S (Linkerd)。您可以进行客户端负载平衡,您可以在此处找到其中的 Java 解决方案。
| 归档时间: |
|
| 查看次数: |
5308 次 |
| 最近记录: |