HAProxy 优雅重载,零丢包

Con*_*lor 49 debian haproxy

我正在运行一个 HAProxy 负载平衡服务器来平衡多个 Apache 服务器的负载。我需要在任何给定时间重新加载 HAProxy 以更改负载平衡算法。

这一切都很好,除了我必须在不丢失单个数据包的情况下重新加载服务器(目前重新加载平均成功率为 99.76%,每秒 1000 个请求持续 5 秒)。我对此进行了很多小时的研究,并找到了以下用于“正常重新加载”HAProxy 服务器的命令:

haproxy -D -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)
Run Code Online (Sandbox Code Playgroud)

然而,与普通的旧版相比,这几乎没有影响service haproxy reload,它仍然平均下降了 0.24%。

有没有办法在没有任何用户丢包的情况下重新加载 HAProxy 配置文件?

Mxx*_*Mxx 37

根据https://github.com/aws/opsworks-cookbooks/pull/40和因此http://www.mail-archive.com/haproxy@formilux.org/msg06885.html你可以:

iptables -I INPUT -p tcp --dport $PORT --syn -j DROP
sleep 1
service haproxy restart
iptables -D INPUT -p tcp --dport $PORT --syn -j DROP
Run Code Online (Sandbox Code Playgroud)

这具有在重新启动之前删除 SYN 的效果,因此客户端将重新发送此 SYN,直到它到达新进程。

  • @DmitriDB 您应该将“$PORT”替换为“haproxy”正在侦听的实际端口。如果 haproxy 正在侦听多个端口,请将 `--dport $PORT` 替换为 `--dports $PORTS_SEPARATED_BY_COMMAS`,例如,`--dports 80,443`。 (6认同)
  • iptables 1.4.7 (Centos 6.7) - 如果要使用 --dports,还必须指定 -m mulitport。所以它的“iptables -I INPUT -p tcp -m multiport --dports 80,443 --syn -j DROP”,同样的 -D (2认同)

Ste*_*sen 29

Yelp 分享了一种基于细致测试的更复杂的方法。这篇博客文章深入探讨,非常值得花时间来充分欣赏它。

真正的零停机时间 HAProxy 重新加载

tl;dr 使用 Linux tc(流量控制)和 iptables 在 HAProxy 重新加载并且将两个 pid 连接到同一端口 ( SO_REUSEPORT) 时临时排队 SYN 数据包。

我不习惯在 ServerFault 上重新发布整篇文章;不过,这里有一些摘录来激起你的兴趣:

通过延迟进入我们在每台机器上运行的 HAProxy 负载均衡器的 SYN 数据包,我们能够在 HAProxy 重新加载期间最大限度地减少对流量的影响,这使我们能够在 SOA 中添加、删除和更改服务后端,而不必担心会显着影响用户流量。

# plug_manipulation.sh
nl-qdisc-add --dev=lo --parent=1:4 --id=40: --update plug --buffer
service haproxy reload
nl-qdisc-add --dev=lo --parent=1:4 --id=40: --update plug --release-indefinite

# setup_iptables.sh
iptables -t mangle -I OUTPUT -p tcp -s 169.254.255.254 --syn -j MARK --set-mark 1

# setup_qdisc.sh
## Set up the queuing discipline
tc qdisc add dev lo root handle 1: prio bands 4
tc qdisc add dev lo parent 1:1 handle 10: pfifo limit 1000
tc qdisc add dev lo parent 1:2 handle 20: pfifo limit 1000
tc qdisc add dev lo parent 1:3 handle 30: pfifo limit 1000

## Create a plug qdisc with 1 meg of buffer
nl-qdisc-add --dev=lo --parent=1:4 --id=40: plug --limit 1048576
## Release the plug
nl-qdisc-add --dev=lo --parent=1:4 --id=40: --update plug --release-indefinite

## Set up the filter, any packet marked with “1” will be
## directed to the plug
tc filter add dev lo protocol ip parent 1:0 prio 1 handle 1 fw classid 1:4
Run Code Online (Sandbox Code Playgroud)

要点:https : //gist.github.com/jolynch/97e3505a1e92e35de2c0

为 Yelp 分享如此惊人的见解干杯。


ger*_*tas 10

还有另一种更简单的方法来重新加载 haproxy,真正的零停机时间——它被命名为iptables 翻转(这篇文章实际上是对 Yelp 解决方案的 Unbounce 响应)。它比接受的答案更清晰,因为不需要丢弃任何可能导致长时间重新加载问题的数据包。

简而言之,该解决方案包括以下步骤:

  1. 让我们有一对 haproxy 实例 - 第一个活动接收流量,第二个处于备用状态,不接收任何流量。
  2. 您可以随时重新配置(重新加载)备用实例。
  3. 一旦备用节点准备好新配置,您将所有新连接转移到备用节点,该节点成为新的活动节点。Unbounce 提供了bash 脚本,它用几个简单的iptable命令来完成翻转
  4. 暂时您有两个活动实例。您需要等到与旧活动的打开连接停止。时间取决于您的服务行为和保持活动设置。
  5. 旧的活动站点的流量变成新的备用站点- 您又回到了第 1 步。

此外,该解决方案可用于任何类型的服务(nginx、apache 等),并且具有更高的容错性,因为您可以在其上线之前测试备用配置。