我需要在多个“真实服务器”之间对 UDP 流量进行负载平衡,并以真正的循环方式进行。我从 keepalived 开始,但意外地发现,LVS 将 UDP 流量视为“连接”(无论 UDP 是什么......)。实际上,这意味着来自特定客户端的所有流量始终都流向同一个“真实服务器”(这很重要,因为某些客户端可能会产生如此大量的流量,以至于单个后端将不堪重负) .
显然,这是预期的行为,但是最近的 LVS 版本有一个“--ops”标志,这使得 LVS 绕过其上述行为,以便独立处理每个 UDP 数据报(这就是我想要的!)。但是(总有一个但是..)这个功能没有从 keepalived.conf 中公开。
有什么解决办法吗?
- 在 UDP 后端之间进行循环分配
- 检测“死”后端并将它们从循环法中移除(当它们变得“活跃”时将它们添加回来也很有用)
显然应该是基于 Linux 的。任何形式的 DNS 循环在这里都不会真正起作用,因为客户端无法识别 DNS。
PS 我打算尝试 pulse/piranha,但通过阅读我收集的文档,它也不会公开“--ops”标志。我也打算给mon一个尝试(让mon检查后端并通过直接调用 ipvsadm 添加/删除 realservers)。
要求满足如下:
我已经安装了更新版本的 ipvsadm(及其内核模块),它支持
--ops
标志 (1.26)。由于 keepalived 不会在其配置文件中公开此标志,因此您必须手动应用它。幸运的是,您可以在创建“虚拟服务”后执行此操作(就普通 ipvsadm 而言,您可以先ipvsam -A
创建一个没有虚拟服务的虚拟服务--ops
,然后再ipvsadm -E
添加一个数据包调度)。由于 keepalived 为您创建了虚拟服务,您所要做的就是在创建后对其进行编辑,这发生在该虚拟服务器获得法定人数时(基本上,有足够数量的工作真实服务器)。这是它在
keepalived.conf
文件中的样子:这行得通,但是我在这个设置中遇到了很多问题(有点):
quorum_up
在法定人数上升和脚本执行之间有很小的时间间隔(不到一秒,更像是 1/10) 。在此期间设法通过导向器的任何数据报都将在 ipvsadm 中创建一个连接条目,并且即使在--ops
添加标志之后,来自该源主机/端口的其他数据报也将停留在同一真实服务器上。您可以通过确保虚拟服务在创建后永远不会被删除来最大限度地减少发生这种情况的可能性。你通过指定inhibit_on_failure
在你的真实服务器定义中标记,这样当相应的真实服务器关闭时它们不会被删除(当所有真实服务器被删除时,虚拟服务也被删除),而是它们的权重设置为零(然后它们停止接收流量)。因此,数据报唯一可以溜走的时间是在 keepalived 启动期间(假设您当时至少有一个真实服务器,以便立即获得法定人数)。--ops
处于活动状态时,director 不会重写 realservers 发送给客户端的数据报的源主机/端口,因此源主机/端口是发送此特定数据报的 realserver 的源主机/端口。这可能是个问题(这是为我的客户准备的)。您可以通过SNAT
使用 iptables 处理这些数据报来修改它。--ops
。据推测,问题在于数据包调度算法在每个数据报上触发,而不仅仅是“连接”中的第一个数据报(如果这甚至适用于 UDP ..)。我实际上还没有找到“修复”它的方法,但也许我还没有足够努力。系统有一些特定的负载要求,在该负载下处理器使用不会达到最大值;也没有任何丢失的数据报,所以这个问题不被认为是一个问题。尽管如此,它仍然相当令人担忧。总结:设置确实有效(也在负载下),但是必须克服的障碍和我遇到的问题(尤其是 №3.. 也许有人知道解决方案?),意味着,给定时间,我会'我使用了一个用户空间程序(可能是用 C 编写的)来侦听 UDP 套接字并在真实服务器之间分发接收到的数据报,结合一些可以为我检查真实服务器健康状况的东西,
SNAT
在 iptables 中重写源主机/端口和在 HA 的 VRRP 模式下保持活动状态。必须有一种方法可以通过多路径路由来做到这一点……
负载均衡器和 realserver 在子网 (10.0.0/24) 中共享 IP。对于两个真实服务器,您从另一个子网添加相同的 IP 作为环回接口 (172.16.1.1/32) 的辅助 IP。您的服务将在此地址上侦听。
然后你可以使用:
但到目前为止,好消息是:显然最近的 linux 内核将缓存路由,以便来自同一源的数据包仍将最终到达同一目的地。有一些补丁可以禁用这种行为,但它们似乎都是针对旧内核的(例如 2.4 内核的多路径均衡补丁,2.6 中的 mpath)。也许更彻底的搜索可能会为您找到最新内核的工作补丁。
您可以通过为 10.0.0.2 和 10.0.0.3 运行 CARP 轻松实现故障转移。这样,当 A 出现故障时,B 接管 10.0.0.2。