我有一个应用程序,客户端通过基于 TCP 的简单协议(通过 TLS/SSL)连接到服务器。在开发过程中,在我们构建应用程序的几个月里,这种方法一直运行良好。最近,在我们准备发布时,我已将 HAProxy 添加到组合中,以促进某种顺序的负载分配。从技术上讲,一切都正常,但问题是,客户端现在看到完全随机的超时。它们通常不一致,但大约持续 60 秒。有时它可能在 25 秒后发生。haproxy 将 TCP 连接转发到的服务器会通知并干净地断开连接,问题是您不希望一堆同时的连接毫无理由地中断并一遍又一遍地重新连接。除了其他方面之外,这还会对我们的发布/订阅基础设施产生影响。客户端足够聪明,可以立即重新连接 - 但这不是我们想要的行为。负责通过 SSL 接受这些 TCP 连接的服务器不需要保持活动状态。我将继续假设我的 HAProxy 配置中有一些我没看到的隐式值导致了这些随机超时,或者需要 TCP 保持活动。然而,超时并不总是一致的事实让我怀疑是不是这样。如果每次都是 60 秒,我会确信这是一个配置问题。在这个特定情况下,它并不总是 60 秒。这是我现在的配置:
global
stats socket /home/haproxy/status user haproxy group haproxy
log 127.0.0.1 local1 info
# log 127.0.0.1 local5 info
maxconn 4096
ulimit-n 8250
# typically: /home/haproxy
chroot /home/haproxy
user haproxy
group haproxy
daemon
quiet
pidfile /home/haproxy/haproxy.pid
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
maxconn 2000
contimeout 5000
clitimeout 60000
srvtimeout 60000
# Configuration for one application:
# Example: listen myapp 0.0.0.0:80
listen www 0.0.0.0:443
mode tcp
balance leastconn
# Example server line (with optional cookie and check included)
# server srv3.0 10.253.43.224:8000 srv03.0 check inter 2000 rise 2 fall 3
# Status port (by default, localhost only...for debugging purposes)
server ANID3 10.0.1.2:8888 check inter 3000 rise 2 fall 3 maxconn 500
server ANID1 10.0.1.3:8888 check inter 3000 rise 2 fall 3 maxconn 500
server ANID2 10.0.1.4:8888 check inter 3000 rise 2 fall 3 maxconn 500
listen health 0.0.0.0:9999
mode http
balance roundrobin
stats uri /haproxy-status
我通过让客户端绕过 HAProxy 直接进入单个应用服务器来验证问题所在,在这个服务器上没有超时,一切都很顺利。只要我通过我们的两个 haproxy 服务器之一路由它,就会发生随机断开连接,持续时间在 25-60 秒之间。
感谢您查看此内容。这确实令人沮丧,但我确信这是因为我对 HAProxy 对我的客户端的具体期望缺乏了解。
答案1
应该没有理由提前关闭连接,我甚至不明白为什么会发生这种情况。您的超时设置为 60 秒,因此应该是 60 秒。
嗯等一下,你不是在跑步吗哈普罗西在具有快速运行时钟的虚拟机中?在某些虚拟机中,这是一个问题,时钟有时运行得太快(超过正确速度的两倍)或太慢,每分钟出现一次大跳跃。Haproxy 知道如何防御它可以检测到的过长暂停和时间跳跃,但显然它无法防御系统未报告的时钟运行过快。
如果你在虚拟机中,你可以尝试这个:
$ while sleep 1; do date; done
让它运行一两分钟。自己检查它是否以正确的速度运行。自从我上次观察到这个讨厌的问题已经有一段时间了,但这并不意味着它不会再次发生。
顺便说一句,您应该在 TCP 部分中设置“ option tcplog
”并检查日志。然后您将从 haproxy 的角度看到这是超时、客户端或服务器中止,以及在多长时间后中止。
答案2
由于时间是可变的,并且您已明确确认后端不负责,因此不太可能是超时设置。
奇怪的是,这会让我找到一个解决方案,也许是重新启动服务。
如果某些东西在 cron 上重新启动 HAProxy(例如 monit - 每 60 秒轮询一次),则可能意味着会话在终止前最多持续 60 秒或更短。
仔细检查 HAProxy 上的正常运行时间,如果它总是在一分钟左右的时间里 - 这就是答案。
此外,也许值得查看 HAProxy 的统计数据,以确保您没有达到任何硬性会话限制,从而导致达到替代超时。如果maxqueue
队列中的请求数少于 ,则在timeout queue
几秒钟内,如果在该超时之后未找到未饱和的服务器,则请求将被丢弃。
答案3
试试这个,我已经解决了这个问题。
listen mysql-slaves
bind 0.0.0.0:3306
mode tcp
maxconn 20000
option mysql-check user haproxy
balance roundrobin
contimeout 5000
clitimeout 50000
srvtimeout 50000
....
答案4
你可以测试一下这个吗:
defaults
timeout client 60000
option http-server-close
而不是 clitimeout option http-server-close
,:
设置“option http-server-close”可在服务器端启用 HTTP 连接关闭模式,同时保持在客户端支持 HTTP 保持活动和流水线的能力。
http://cbonte.github.io/haproxy-dconv/2.3/configuration.html#option%20http-server-close