node.js交错保持对大量tcp客户端的影响

时间:2012-08-08 18:20:40

标签: javascript node.js asynchronous tcp scalability

我正在尝试将服务器中的keep alives发送到一堆tcp客户端。为了减少响应中的服务器负载,我想将保持活动分开。

如果我有3000个tcp客户端,并且60s保持活动间隔,我需要在60s内错开保持活动消息并且每秒发送50次保持活动。

假设:

  1. 很多tcp连接(成千上万)
  2. Tcp连接仍然存在,并且可以预期在几个小时内处于活动状态,最小值
  3. 如果客户端不再连接,服务器需要在60秒内知道
  4. 来自服务器和客户端的其他信息将来回发送
  5. 来自客户端的保持活动返回消息包含有用的数据(我认为排除了UDP)
  6. 目前,我的想法是将我的tcp连接存储为标准的javascript对象,其中一些id映射到特定的连接本身。然后,每一秒,我得到这个对象的键数组,并发送保持alives到这些的一部分。

    这是一个好方法吗?是否有更好的方法或其他我应该考虑的事情?

    我最初尝试解决问题的示例代码:

    var KEEP_ALIVE_INTERVAL = 1000; // time between groups
    var KEEP_ALIVE_CYCLE = 3; // number of groups
    var tcp_conns = {
        a:"a",
        b:"b",
        c:"c",
        d:"d",
        e:"e",
        f:"f",
        g:"g",
        h:"h",
        i:"i"
    };
    
    var intervalCounter = 0;
    setInterval(function() {
    
        console.log("sending keep alives intervalCounter="+intervalCounter);
    
        var numConns = Object.keys(tcp_conns).length;
        var connFactor = Math.ceil( numConns / KEEP_ALIVE_CYCLE );
        var lowerLimit = connFactor*intervalCounter-1;
        var upperLimit = connFactor*(intervalCounter+1);
    
        console.log("connFactor="+connFactor+", limits=["+lowerLimit+","+upperLimit+"]");
    
        // Is this even async???
        var keys = Object.keys(tcp_conns)
        for (var i = 0; i < keys.length; i++) {
            if(i>lowerLimit && i<upperLimit){
                var key = keys[i]
                var val = tcp_conns[key]
                console.log(" id="+key+" => "+val);
            }
        }
    
        intervalCounter++;
        if(intervalCounter==KEEP_ALIVE_CYCLE){
            intervalCounter=0;
        }
    }, KEEP_ALIVE_INTERVAL);
    

1 个答案:

答案 0 :(得分:1)

我不会明确地管理包含所有连接的集合,而是每隔45到75秒随机发送一次保持活动。这样,保持活动将随着时间的推移而扩散。我不确定下面的代码是否正常工作,但你会得到基本的想法。

  • 我假设'PONG'作为一个单块到达,可能不是这样。
  • 小心避免泄露听众。在这里,我发送PING时添加了一个“数据”处理程序,当我得到PONG时我将其删除。不是最有效的解决方案。

以下是代码:

var KEEP_ALIVE_TIMEOUT = 120*1000,
    MIN_KEEP_ALIVE = 45*1000,
    MAX_KEEP_ALIVE = 75*1000;

function randomInt(min, max) {
    return Math.random()*(max - min) + min;
}

net.createServer(function(conn) {
  function ping() {
     var keepAliveTimer = setTimeout(function() {
       conn.destroy();
       console.log('timeout !');
     }, KEEP_ALIVE_TIMEOUT);

     conn.write('PING\r\n');

     conn.on('data', function onData(chunk) {
        if(chunk.toString() !== 'PONG\r\n')
          return handleSomethingElse();

        clearTimeout(keepAliveTimer);
        conn.removeListener('data', onData);
        setTimeout(ping, randomInt(MIN_KEEP_ALIVE, MAX_KEEP_ALIVE));
     });
  }

  ping();
});