NodeJS Socket.io:状态CLOSE_WAIT和FIN_WAIT2中的许多连接没有释放

时间:2013-12-26 00:11:55

标签: node.js socket.io

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

有大约300个同时连接。几个小时后(大约1或2个小时,它不会立即显示),某些连接将持续处于 CLOSE_WAIT FIN_WAIT2 状态。

这些未死亡的连接随着时间的推移呈线性增长。当连接数达到限制(默认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

可能的解决方案

1。定期触摸js文件

使用Nodemon Package运行js文件,当更改文件的上次修改时间时,nodemon将重新启动服务,并释放所有先前的未连接连接( CLOSEWAIT FINWAIT2 < /强>)

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。减少保持活动超时

让操作系统在短时间内自动关闭连接,但我还没试过。

问题

我找到了解决问题的方法。但上述解决方案并未真正解决状态 CLOSE_WAIT FIN_WAIT2 问题的持续连接。我发现这是服务器( CLOSE_WAIT )或客户端( FIN_WAIT2 )无法正确关闭连接的结果。我认为socket.io会在一些超时后强行关闭这些错误的连接。但它似乎无法正常工作。

我尝试在测试环境中重新显示状态 CLOSE_WAIT FIN_WAIT2 问题。但它从未显示出这些连接情况。

  1. 连接套接字服务器并断开网络连接后
  2. 长时间连接套接字服务器
  3. 我发现之前有人问过相关问题(Many stale connections in state CLOSE_WAIT and FIN_WAIT2),但仍无法找到解决方法。有谁知道如何解决这个问题??

    由于

3 个答案:

答案 0 :(得分:3)

我尝试使用多个连接同时连接套接字服务器,我发现一些客户端套接字将使用相同的 SOCKET ID (从xhr获取它看起来像 nmXTMmCGNQp4EncrfHqj )建立连接。我建立所有连接后关闭浏览器,它将导致许多CLOSE_WAIT连接而不释放。一些连接将关闭(基于已生成的唯一SOCKET ID 的数量)。因为服务器将从 SOCKET ID 建立TCP / IP连接。但是,如果连接池中已存在 SOCKET ID 连接,则此连接将不会存储在连接池中。因此,当客户端发送FIN数据包以尝试关闭连接但在服务器连接池中不存在时。服务器将始终不发送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 连接时,不要从 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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

如果您使用本机cluster模块并生成工作程序,请注意,如果您的工作进程在连接到它的客户端被强行杀死(即由于系统内存不足),它将留下CLOSE_WAIT套接字将无限期地阻塞系统资源。

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

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