UDP 的每个数据包循环负载平衡

UDP 的每个数据包循环负载平衡

我需要在多个“realserver”之间对 UDP 流量进行负载平衡,并以真正的循环方式进行。我已开始使用 keepalived,但意外发现 LVS 将 UDP 流量视为“连接”(无论 UDP 中是什么...)。实际上,这意味着来自特定客户端的所有流量始终流向同一个“realserver”(这很重要,因为某些客户端可能会产生如此大的流量,以至于单个后端将不堪重负)。

显然,这是预期的行为,然而较新的 LVS 版本有一个“--ops”标志,它使 LVS 绕过其上述行为,以便每个 UDP 数据报都得到独立处理(这就是我想要的!)。但是(总有一个但是...)此功能未在 keepalived.conf 中公开。

有没有什么解决方案可以让我

  • 在 UDP 后端之间进行循环分发
  • 检测“死”的后端并将其从循环中删除(当它们恢复“活跃”时将它们重新添加回来也很有用)

显然应该基于 Linux。任何形式的 DNS 循环在这里都无法真正发挥作用,因为客户端无法识别 DNS​​。

PS 我打算尝试 pulse/piranha,但从我收集到的文档来看,它也没有公开“--ops”标志。我还打算给星期一尝试(做星期一通过直接调用 ipvsadm 检查后端并添加/删除真实服务器)。

答案1

要求得到满足,如下所示:

我安装了较新版本的 ipvsadm(及其内核模块),该版本支持该--ops标志(1.26)。由于 keepalived 未在其配置文件中公开此标志,因此您必须手动应用它。幸运的是,您可以这样做“虚拟服务”已创建(就普通的 ipvsadm 而言,您可以先创建ipvsam -A一个没有的虚拟服务--ops,然后ipvsadm -E为其添加一个数据包调度)。

由于 keepalived 会为您创建虚拟服务,因此您所要做的就是在创建后对其进行编辑,这在此虚拟服务器获得法定人数时发生(基本上,有足够数量的工作 realserver)。它在文件中的样子如下keepalived.conf

virtual_server <VIP> <VPORT> {
    lb_algo rr
    lb_kind NAT
    protocol UDP
    ...

    # Enable one-packet scheduling when quorum is gained
    quorum_up "ipvsadm -E -u <VIP>:<VPORT> --ops -s rr"

    ... realserver definitions, etc ...
}

这是可行的,但是我在使用此设置时遇到了许多问题(有点):

  1. 仲裁启动和脚本执行之间存在短暂的时间间隔(不到一秒,更像是 1/10)quorum_up。在此期间,任何设法通过导向器的数据报都将在 ipvsadm 中创建一个连接条目,并且来自该源主机/端口的其他数据报将停留在同一台 realserver 上即使--ops添加了标志。您可以通过确保虚拟服务在创建后永远不会被删除来最大限度地减少这种情况发生的可能性。您可以通过inhibit_on_failure在 realserver 定义中指定标志来实现这一点,以便在相应的 realserver 关闭时不会删除它们(当所有 realserver 都被删除时,虚拟服务也会被删除),而是将它们的权重设置为零(然后它们停止接收流量)。因此,数据报唯一可以漏掉的时间是在 keepalived 启动期间(假设您当时至少有一个 realserver 处于启动状态,这样就会立即获得法定人数)。
  2. --ops处于活动状态时,director 不会重写 realserver 发送给客户端的数据报的源主机/端口,因此源主机/端口是发送此特定数据报的 realserver 的主机/端口。这可能是一个问题(对于我的客户端)。您可以通过SNAT使用 iptables 修改这些数据报来修改它。
  3. 我注意到了显著的系统控制器负载过大时的 CPU 负载。事实证明,CPU 被 ksoftirqd 占用。如果关闭,则不会发生这种情况--ops。据推测,问题在于数据包调度算法在每个数据报上触发,而不仅仅是“连接”中的第一个数据报(如果这适用于 UDP...)。我实际上还没有找到“修复”该问题的方法,但也许我还没有足够努力。系统有一些特定的负载要求,并且在这种负载下处理器使用率不会达到最大值;也没有丢失任何数据报,因此这个问题不算是大问题。但它仍然相当令人担忧。

摘要:该设置肯定有效(在负载下也可以),但是必须经历许多困难和我遇到的问题(尤其是问题 3,也许有人知道解决方案?),这意味着,如果有时间,我会使用一个用户空间程序(可能是用 C 编写的)用于监听 UDP 套接字并在 realserver 之间分发接收到的数据报,同时结合某些东西来检查 realserver 的运行状况,SNAT在 iptables 中重写源主机/端口,并在 VRRP 模式下保持活跃以实现 HA。

答案2

一定有一种方法可以通过多路径路由来实现这一点......

负载均衡器和真实服务器共享子网中的 IP(10.0.0/24)。对于两个真实服务器,您从另一个子网添加相同的 IP,作为环回接口(172.16.1.1/32)的辅助 IP。您的服务将在此地址上进行监听。

                              +-------------------------------------+
                         +----|A: eth0:10.0.0.2/24 lo:172.16.1.1/32 |
+--------------------+   |    +-------------------------------------+
|LB eth0:10.0.0.1/24 |---|
+--------------------+   |    +-------------------------------------+
                         +----|B: eth0:10.0.0.3/24 lo:172.16.1.1/32 |
                              +-------------------------------------+

然后你可以使用:

 ip route add 172.16.1.1/32 nexthop via 10.0.0.2 nexthop via 10.0.0.3

但到目前为止,好消息是:显然,最新的 Linux 内核将缓存路由,以便来自同一源的数据包仍将到达同一目的地。有一些补丁可以禁用此行为,但它们似乎都是针对较旧的内核(例如 2.4 内核的多路径均衡补丁,2.6 中的 mpath)。也许更彻底的搜索可能会为您找到适用于最新内核的补丁。

您可以通过为 10.0.0.2 和 10.0.0.3 运行 CARP 轻松实现故障转移。这样,当 A 发生故障时,B 可以接管 10.0.0.2。

相关内容