HAProxy + nginx 在大约 24 小时内达到最大 numtcpsock

HAProxy + nginx 在大约 24 小时内达到最大 numtcpsock

我正在运行一个相对简单的 VPS(Media Temple (ve)),上面有几个基于 PHP 的网站,以及(最终)几个节点服务器。为了启用 WebSockets 支持,我在端口 80 上使用 HAProxy,该端口路由到 nginx 或特定的 Node 进程。

不过,我最近遇到了一个问题,在大约 24 小时内,我的服务器达到了允许的最大打开 TCP 连接数(numtcpsock在 Parallels Power Panel 中,设置为 1,000)。单独运行 nginx 不会导致此问题,并且我目前没有活动的 Node 后端服务器。Nginx 通过 UNIX 域套接字连接到 PHP(同样,单独使用 nginx 不会出现此问题)。有什么想法可能导致此问题?我的配置:

global
    ## 00-base
    maxconn     500
    nbproc      2
defaults
    ## 00-base
    mode        http
frontend all
    ## 00-ports
    bind 0.0.0.0:80
    ## 10-config
    timeout client 86400000
    default_backend nginx
backend nginx
    ## 00-timeouts
    timeout http-keep-alive 5000
    timeout server 10000
    timeout connect 4000
    ## 10-servers
    server main localhost:8000

提前致谢!

更新:经过一番lsof研究,我能够确定 90% 以上的开放 TCP 套接字确实归 HAProxy 所有,并且绝大多数处于CLOSE_WAITFIN_WAIT2状态。这是 HAProxy 错误吗?这看起来像是某种文件描述符泄漏,除非是我的配置错误。

更新2:我注意到lsof输出中有一个模式。在我看来,发生的事情是 nginx 正在关闭与 HAProxy 的内部连接,但在 HAProxy 正式关闭它之前,它会尝试关闭与客户端的外部连接(将其放入FIN_WAIT2)。由于 FIN 永远不会到来,因此 nginx 和 HAProxy 之间的连接将CLOSE_WAIT永远保持。现在唯一的问题是:为什么会发生这种情况?

答案1

问题是由于您的超时时间过长造成的。超时时间为 24 小时,同时连接数限制为 1000,显然客户端会以不正当的方式断开连接。请使用更合理的超时时间,从几分钟到最多几小时,在互联网上使用 1 天的超时时间确实毫无意义。正如 DukeLion 所说,系统正在等待 haproxy 关闭连接,因为 haproxy 没有收到来自客户端的关闭。

Haproxy 在 TCP 和 WebSocket 的隧道模式下工作,它遵循通常的四向关闭:

- receive a close on side A
- forward the close on side B
- receive the close on side B
- forward the close on side A

在您的例子中,我假设 A 端是服务器,B 端是客户端。因此,nginx 在一段时间后关闭,套接字进入 CLOSE_WAIT 状态,haproxy 将关闭转发给客户端,此套接字进入 FIN_WAIT1 状态,客户端确认,将套接字传递到 FIN_WAIT2 状态,然后什么也没发生,因为客户端已经消失,这在网络上很常见。您的超时意味着您希望这种情况持续 24 小时。

24 小时后,您的会话将在客户端开始超时,因此 haproxy 将终止它们并将关闭转发到 nginx 端,从而将其也删除。但显然您不希望发生这种情况,WebSocket 的设计使得空闲连接可以透明地重新打开,因此没有理由将空闲连接保持打开状态 24 小时。没有防火墙会一直保持它!

答案2

很多套接字处于 CLOSE_WAIT 状态对服务器来说是极其糟糕的。当内核等待用户空间软件接受套接字关闭时,就会出现此状态。如果很多套接字长时间处于此状态 - 这意味着使用它的软件没有响应。通常,处于此状态的套接字会消耗相对大量的内核 CPU 时间。

我认为您情况下的 CLOSE_WAITs 是 FIN_WAIT2 的次要部分 - HAproxy 正在等待客户端连接关闭,然后在此之后关闭与 NGINX 的连接。

FIN_WAIT2 是等待另一方确认套接字关闭的状态。出现很多这样的情况并不是很糟糕,但它可能表示网络拥塞或严重丢失。

您可以尝试nolinger使用 haproxy 选项来更快地关闭连接。但要小心,这会破坏保证交付的 tcp 机制。

相关内容