HAProxy 关闭长期存在的 TCP 连接,忽略 TCP keepalive

HAProxy closes long living TCP connections ignoring TCP keepalive

我已经配置了 HAProxy(1.5.4,但我也尝试过 1.5.14)以在 TCP 模式下平衡两个在 5672 端口上公开 AMQP 协议(​​WSO2 Message Broker)的服务器。 客户端通过 HAProxy 创建并使用与 AMQP 服务器的永久连接。

我已经更改了客户端和服务器 TCP keepalive 超时,设置为 net.ipv4.tcp_keepalive_time=120 (CentOS 7).

在 HAProxy 中,我将超时 client/server 设置为 200 秒(>120 秒的保活数据包)并使用选项 clitcpka。

然后我启动了 wireshark 并嗅探了所有 tcp 流量:在客户端发出最后一个请求后,tcp keepalived 数据包在 120 秒后定期发送,但在客户端发出最后一个请求后 200 秒后,连接关闭(因此忽略 keepalived 数据包)。

配置如下:

haproxy.conf

global
    log 127.0.0.1   local3
    maxconn 4096
    user haproxy
    group haproxy
    daemon
    debug

listen messagebroker_balancer 172.19.19.91:5672
    mode tcp
    log global
    retries 3
    timeout connect 5000ms
    option redispatch
    timeout client 200000ms
    timeout server 200000ms
    option tcplog
    option clitcpka 
    balance leastconn
    server s1 172.19.19.79:5672 check inter 5s rise 2 fall 3
    server s2 172.19.19.80:5672 check inter 5s rise 2 fall 3

TCP keep alive 位于传输层,仅用于连接上的一些流量,因此 中间 系统(如数据包过滤器)不会丢失任何状态,并且结束系统可以注意到与另一端的连接是否断开(可能是因为崩溃或网络电缆断开)。

TCP keep alive 与您明确设置为 200 秒的应用程序级空闲超时无关:

timeout client 200000ms
timeout server 200000ms

如果连接空闲,即没有数据传输,则会触发此超时。 TCP keep alive 不传输任何数据,这些数据包的负载是空的。

timeout client 在响应客户端 OS 上检测到死客户端应用程序。您总是可以拥有一个占用连接但不与您通话的应用程序。这很糟糕,因为连接数不是无限的 (maxconn)。

同理,后端设置timeout server

这些选项用于 haproxy 与应用程序对话。现在,有一个完全独立的检查,其中 OS 与 OS 对话(不接触应用程序或 haproxy):

使用 option clitcpkaoption srvtcpkaoption tcpka 您允许 OS 检测并终止非活动连接,即使 haproxy 不主动检查它.这主要需要 OS 设置 (Linux).

如果 110 秒内没有发送数据,则立即发送第一个 keep-alive (KA),但不要终止连接:

 sysctl net.ipv4.tcp_keepalive_time=110

每次 KA 后等待 30 秒,在此连接上启用后:

 sysctl net.ipv4.tcp_keepalive_intvl=30

允许 3 个 KA 未被确认,然后终止 TCP 连接:

 sysctl net.ipv4.tcp_keepalive_probes=3

在这种情况下,OS 在数据包停止到来 200 秒后终止连接。