简体   繁体   English

node.js令人难以置信的存活到大量的tcp客户端

[英]node.js staggering keep alives to large amount of tcp clients

I'm trying to send keep alives from a server to a bunch of tcp clients. 我正在尝试从服务器向一堆tcp客户端发送保持活动状态。 To reduce the server load on the responses, I want to spread the keep alives apart. 为了减少服务器在响应中的负载,我想分散保持活动。

If I have 3000 tcp clients, and 60s keep alive interval, I need to stagger keep alive messages over the 60s and send 50 keep alives every second. 如果我有3000个tcp客户端,并且60s保持活动间隔,则需要在60s上错开保持活动消息,并每秒发送50个保持活动。

Assumptions: 假设:

  1. Lots of tcp connections (in the thousands) 大量的TCP连接(数以千计)
  2. Tcp connections persist and can be expected to be active for several hours, minimum Tcp连接持续存在,并且可以预期至少几个小时处于活动状态
  3. Server needs to know within say 60s if a client is no longer connect 服务器需要在60秒内知道客户端是否不再连接
  4. Other information from the server and clients will be sent back and forth 来自服务器和客户端的其他信息将被来回发送
  5. Keep alive return messages from clients contain useful data (which I think rules out UDP) 保持活跃的客户端返回消息包含有用的数据(我认为这可以排除UDP)

Currently, my thought is to store my tcp connections as a standard javascript object, with some id mapping to a particular the connection itself. 目前,我的想法是将tcp连接存储为标准的javascript对象,并将一些id映射到特定的连接本身。 Then, each second, I get the array of keys of this object, and send keep alives to some portion of these. 然后,每秒钟,我获得该对象的键数组,并向其中的某些部分发送保持活动状态。

Is this a good approach? 这是一个好方法吗? Are there better approaches or other things I should consider? 是否有更好的方法或其他我应该考虑的东西?

Example code for my initial stab at the problem: 我最初遇到问题时的示例代码:

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);

Rather than explicitly managing a collection containing all the connections, I'd send keep-alives randomly every 45s to 75s. 我不是显式管理包含所有连接的集合,而是每45s到75s随机发送一次keep-alive。 This way, keep-alives will be spread over time. 这样,保持活动将随着时间的流逝而扩展。 I'm not sure that the following code works as-is, but you'll get the basic idea. 我不确定以下代码是否可以按原样工作,但是您将了解基本概念。

  • I'm assuming that 'PONG' arrives as a single chunk, which might not be the case. 我假设“ PONG”作为单个块到达,事实并非如此。
  • Be careful to avoid leaking listeners. 注意避免泄漏听众。 Here, I add a "data" handler when I send PING, and I remove it when I get PONG. 在这里,我在发送PING时添加一个“数据”处理程序,并在收到PONG时将其删除。 Not the most efficient solution. 不是最有效的解决方案。

Here's the code: 这是代码:

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();
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM