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

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

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

 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 

提前致谢!

更新 :在一点点的ing​​之后,我能够确定90%以上的开放TCP套接字实际上是由HAProxy拥有的,绝大多数是在CLOSE_WAIT或者FIN_WAIT2状态。 这是一个HAProxy错误? 这似乎是某种文件描述符泄漏,除非是我的错误configuration。

更新2 :我注意到在lsof输出模式。 在我看来,nginx正在closures与HAProxy的内部连接,但在HAProxy正式closures之前,它试图closures与客户端的外部连接(将其放入FIN_WAIT2 )。 因为FIN永远不会到来,所以nginx和HAProxy之间的连接永远停留在CLOSE_WAIT 。 现在唯一的问题是:这是为什么发生?

这个问题是由你的超长时间造成的。 由于24小时的超时时间和1000个并发连接的限制,你可以清楚地预料到,用客户端来隔离这种肮脏的方式。 请使用一个更合理的超时时间,从几分钟到最多几小时,在互联网上使用1天超时确实没有意义。 正如DukeLion所说,系统正在等待haproxyclosures连接,因为haproxy没有收到客户端的密码。

Haproxy正在TCP和WebSocket的隧道模式下工作,它遵循通常的4路closures:

 - 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方是客户端。 所以nginxclosures一段时间后,socket去了CLOSE_WAIT,haproxy把close转发给客户端,这个socket去了FIN_WAIT1,客户端确认了,把套接字传给了FIN_WAIT2,然后什么都没有发生,因为客户端已经消失了,这是非常常见的networking上。 而你的超时意味着你想要这样保持24小时。

24小时后,你的会话将在客户端开始超时,所以haproxy将会把它们杀死,然后将它们转移到nginx端,并将其除掉。 但显然你不希望这种情况发生,WebSocket被devise成可以透明地重新打开空闲连接,所以没有理由保持空闲连接24小时。 没有防火墙会保持它的方式!

CLOSE_WAIT中的许多套接字对于您的服务器来说是非常糟糕的事情。 当内核等待用户空间软件接受套接字closures时发生这种状态。 如果很多套接字长时间处于这种状态,就意味着使用它的软件没有反应。 通常这个状态的socket会消耗较多的内核cpu时间。

我想你的情况下的CLOSE_WAIT是次要的FIN_WAIT2 – HAproxy正在等待客户端连接closures,然后closures与NGINX的连接。

FIN_WAIT2是等待对方确认套接字closures的状态。 其中有许多这并不坏,但它可能表明networking拥塞或严重损失。

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