Socket IO 无限循环超过 1000 个连接

Socket IO infinite loop over 1000 connections

我需要对多个套接字连接进行基准测试。我有一个带有以下代码的 nodejs 服务器:

var io = require('./lib/node_modules/socket.io').listen(12345)

io.sockets.on("connect", function(socket) {
    console.log("Socket " + socket.id + " connected.")

    socket.on("disconnect", function() {
        console.log("Socket " + socket.id +" disconnected.")
    })
})

和一个 nodejs 客户端:

var port            = 12345
,   nbSocket        = 1000
,   io              = require("./lib/node_modules/socket.io-client")

for (var i = 1;i <= nbSocket;i++)
{
    var socket = io.connect("http://<<my_ip>>:" + port, {forceNew: true})
}

客户端代码执行时,服务器正确连接套接字,正常结束。

但是如果我们将 nbSocket 更改为 2000,服务器将永远不会结束连接和断开套接字。

我们已经尝试更改限制:

ulimit -n5000

但是没有用。是否还有其他限制或我们错过了什么?

我在 OSX 运行 节点 v0.12.4 和 socket.io v1.3.5 上进行了测试,它开始给我带来问题 nbSocket=5000

尝试将此片段附加到服务器脚本的末尾:

process.on('uncaughtException', function(err) {
    console.info(util.inspect(err, {colors: true}));
});

此外,我稍微更改了您的代码并添加了一个每秒两次打印打开套接字数量的计时器:

var
    util = require('util'),
    io = require('socket.io').listen(12345);

var
    clientCount = 0;

function onClientDisconnect() {
    clientCount--;
}

io.on('connect', function(socket) {
    clientCount++;
    socket.on('disconnect', onClientDisconnect);
});

console.info('Listening...');

setInterval(function () {
    console.info('Number of open sockets: %d', clientCount);
}, 500);

process.on('uncaughtException', function(err) {
    console.info(util.inspect(err, {colors: true}));
});

当打开的套接字数开始接近 5000 时,我开始多次看到这 2 条消息:

{ [Error: accept ENFILE] code: 'ENFILE', errno: 'ENFILE', syscall: 'accept' }
{ [Error: accept EMFILE] code: 'EMFILE', errno: 'EMFILE', syscall: 'accept' }

根据libc manual

  • ENFILE: 整个系统中打开的不同文件太多
  • EMFILE: 当前进程打开的文件过多

所以事实上我的问题是文件描述符的限制,所以通过将上面的代码片段附加到您的服务器脚本来检查它是否也是您的问题。如果出现异常,您应该研究如何 properly increase the limit of open files in your system.