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

KeJ*_*yun 6 node.js socket.io

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

有大约300个同时连接.几个小时后(大约1或2个小时,它没有立即显示),一些连接将持续处于CLOSE_WAITFIN_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
Run Code Online (Sandbox Code Playgroud)

可能是解决方案

1.定期触摸js文件

使用Nodemon Package运行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
Run Code Online (Sandbox Code Playgroud)

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

3.减少保持活动超时

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

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

我尝试在我的测试环境中重新出现状态CLOSE_WAITFIN_WAIT2问题.但它从未显示出这些连接情况.

  1. 连接套接字服务器和断开网络后
  2. 连接套接字服务器很长一段时间

我之前发现有人问相关问题(状态CLOSE_WAIT和FIN_WAIT2中的许多陈旧连接),但仍无法找到解决方案.有谁知道如何解决这个问题?

谢谢

KeJ*_*yun 4

我尝试同时使用多个连接来连接套接字服务器,我发现某些客户端套接字将使用相同的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");
  });
}
Run Code Online (Sandbox Code Playgroud)

修复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
  }
}
Run Code Online (Sandbox Code Playgroud)

以下是socket服务连接状态,运行了大约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
Run Code Online (Sandbox Code Playgroud)
  1. 基准测试socket.io