node.js让大量的tcp客户端大失所望

我试图从服务器发送一堆tcp客户端。 为了减less响应上的服务器负载,我想分开保持活动。

如果我有3000个tcp客户端,并且60秒保持活跃的时间间隔,那么我需要在60年代错开保持活跃的信息,并且每秒发送50个消息。

假设:

  1. 大量的tcp连接(以千计)
  2. TCP连接持续存在,预计可以在最less的几个小时内激活
  3. 服务器需要在60秒之内知道客户端是否不再连接
  4. 来自服务器和客户端的其他信息将被反复发送
  5. 保持活着从客户端返回消息包含有用的数据(我认为排除UDP)

目前,我的想法是存储我的TCP连接作为一个标准的JavaScript对象,有一些id映射到一个特定的连接本身。 然后,每秒钟,我得到这个对象的键的数组,并发送保持活跃的一部分这些。

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

我的初始刺戳问题的示例代码:

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

我没有明确地pipe理一个包含所有连接的集合,而是每隔45s到75s随机发送一次keepalive。 这样,保活会随着时间推移。 我不确定下面的代码是按原样运行的,但是你会得到基本的想法。

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

代码如下:

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