NodeJS Socket.io:处于CLOSE_WAIT和FIN_WAIT2状态的许多连接没有发布

我用ubuntu(12.04)+ nodejs(v0.10.22)+ socket.io(v0.9.14)来传输消息。

有~300个同时连接。 几个小时后(大约1或2小时以上,它不会立即显示),一些连接将持续在CLOSE_WAITFIN_WAIT2状态。

而这些无死angular的连接随着时间而线性增长。 当连接数达到限制(默认1024)时,用户将很难连接套接字服务器,除非某些连接正常释放。

以下是套接字服务连接状态,运行约3小时。

netstat -anl | grep <PORT_OF_NODE_PROCESS> | awk '/^tcp/ {t[$NF]++}END{for(state in t){print state, t[state]} }' FIN_WAIT2 23 LISTEN 1 CLOSE_WAIT 27 TIME_WAIT 12 ESTABLISHED 333 FIN_WAIT1 12 

可能的解决scheme

1.定期触摸js文件

使用Nodemon程序包运行js文件,当更改文件的上次修改时间时,nodemon将重新启动服务,并释放所有以前的未连接( CLOSEWAITFINWAIT2

2.增加连接限制

 sudo vim /etc/security/limits.conf * soft nofile 1024 * hard nofile 2048 root soft nofile 4096 root hard nofile 8192 user1 soft nofile 2048 user1 hard nofile 2048 

尽量让连接难以达到极限。

3.减less保持活动超时

让操作系统在短时间内自动closures连接,但我还没有尝试。

我发现一些可能的解决scheme来解决这个问题。 但上面的解决scheme并没有真正解决与状态CLOSE_WAITFIN_WAIT2问题的持久连接。 我可以发现这是服务器( CLOSE_WAIT )或客户端( FIN_WAIT2 )没有正确closures连接的结果。 我认为socket.io将强制closures这些不正确的连接后,超时。 但似乎不能正常工作。

我尝试在我的testing环境中重新出现状态CLOSE_WAITFIN_WAIT2问题。 但它从来没有显示出这些连接的情况。

  1. 连接套接字服务器并断开networking连接
  2. 长时间连接套接字服务器

我发现之前有人问过相关的问题( 状态为CLOSE_WAIT和FIN_WAIT2的很多陈旧的连接 ),但仍然找不到解决scheme。 有谁知道如何解决这个问题?

谢谢

我尝试使用多个连接来同时连接套接字服务器,我发现某些客户端套接字将使用相同的SOCKET ID (从xhr获得,它看起来像nmXTMmCGNQp4EncrfHqj )来build立连接。 当所有连接build立时,我closures浏览器,并且会导致许多CLOSE_WAIT连接,而不会释放。 一些连接将closures(基于已生成的唯一SOCKET ID的数量)。 因为服务器将从SOCKET IDbuild立TCP / IP连接。 但是,如果连接池中已经存在SOCKET ID连接,则该连接将不会存储在连接池中。 所以当客户端发送FIN数据包尝试closures连接但不存在于服务器连接池中时。 服务器将始终不发送ACK数据包以准备紧密连接。 所以这些连接将保持CLOSE_WAIT状态,而不会释放。

 var host = 'http://socket.server/'; var sockets = []; for(var i=0;i<200;i++){ var socket = io.connect(host,{"force new connection":true}); sockets.push(socket); socket.on("message",function(message){ console.log(message); }); socket.on("disconnect",function(){ console.log("disconnect"); }); } 

修复lib \ manager.js行670。

当连接池中已经存在SOCKET ID连接时,不build立来自SOCKET ID的 TCP / IP连接。

另见: https : //github.com/kejyun/socket.io/commit/8d6c02a477d365f019530b4ec992420dfb90eb09

 if (!this.connected[data.id]) { if (transport.open) { if (this.closed[data.id] && this.closed[data.id].length) { transport.payload(this.closed[data.id]); this.closed[data.id] = []; } this.onOpen(data.id); this.store.publish('open', data.id); this.transports[data.id] = transport; } this.onConnect(data.id); this.store.publish('connect', data.id); //....etc } } 

以下是套接字服务连接状态,运行约6个小时。

 netstat -anl | grep <PORT_OF_NODE_PROCESS> | awk '/^tcp/ {t[$NF]++}END{for(state in t){print state, t[state]} }' FIN_WAIT2 37 LISTEN 1 TIME_WAIT 13 ESTABLISHED 295 FIN_WAIT1 20 
  1. Benchmarkt socket.io

上述解决scheme可能会解决CLOSE_WAIT,但不解决FIN_WAIT2。 这里的最新讨论( https://github.com/LearnBoost/socket.io/issues/1380 )提供了可能的替代解决scheme。 这个讨论还指出,问题是在node.js本身而不是socket.io。

如果您使用本地cluster模块并产生工作,请注意,如果您的工作进程被与其连接的客户端强行杀死(即由于系统内存不足),则会留下CLOSE_WAIT套接字,从而无限期地阻塞系统资源。

解决方法是在您的一个工作人员被操作系统终止时立即终止您的主要Node.js进程。 一旦主Node.js进程被终止,系统将销毁属于死亡工作者的CLOSE_WAIT所有套接字。

另外,从Node.js v4.9.5上的工作进程调用socket.destroy()也会导致套接字处于CLOSE_WAIT状态。 更新到Node.js v6.9.5 LTS为我解决了这个问题。