【问题标题】:NodeJS Socket.io : Many connections in state CLOSE_WAIT and FIN_WAIT2 without releaseNodeJS Socket.io:许多连接处于状态 CLOSE_WAIT 和 FIN_WAIT2 没有释放
【发布时间】:2017-02-13 04:36:04
【问题描述】:

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

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

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

以下为socket服务连接状态,运行约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会重启服务,并释放之前所有的未死连接(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。减少保活超时

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

问题

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

我尝试在我的测试环境中再次出现状态 CLOSE_WAITFIN_WAIT2 问题。但它从不显示这些连接情况。

  1. 连接套接字服务器并断开网络后
  2. 长时间连接socket服务器

我之前发现有人问过相关问题(Many stale connections in state CLOSE_WAIT and FIN_WAIT2),但仍然找不到解决方案。有谁知道如何解决这个问题??

谢谢

【问题讨论】:

    标签: node.js socket.io


    【解决方案1】:

    我尝试使用多个连接同时连接socket服务器,我发现一些客户端socket会使用相同的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
      }
    }
    

    以下是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
    
    1. Benchmarkt socket.io

    【讨论】:

    • 那么你是否真的将这个补丁作为拉取请求提交了?其他人(包括我自己)也遇到过这个问题。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-09
        • 2012-02-08
        • 1970-01-01
        • 2021-09-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多