NodeJs:如何处理大量的计时器?

时间:2013-08-14 08:23:59

标签: node.js timer socket.io settimeout

我使用socket.io通过websockets发送数据包。它们似乎不时消失。所以我必须实施某种确认系统。我的想法是立即响应带有ACK数据包的数据包。如果服务器在给定时间内没有收到此ACK数据包,他将重新发送(最多3次,然后断开套接字)。

我的第一个想法是在发送数据包后启动计时器(setTimeout)。如果发生超时事件,则必须再次发送数据包。如果ACK将到达,超时将被删除。非常容易和短暂。

var io = require('socket.io').listen(80);

// ... connection handling ...

function sendData(someData, socket) {
  // TODO: Some kind of counter to stop after 3 tries.
  socket.emit("someEvent", someData);
  var timeout = setTimeout(function(){ sendData(someData, socket); }, 2000);
  socket.on("ack", function(){
    // Everything went ok.
    clearTimeout(timeout);
  });
}

但是我会让1k-3k的客户端连接很多流量。我无法想象,同时运行的10k计时器可由NodeJS处理。 更糟糕:我读到如果没有时间,NodeJS将不会触发该事件。

如何实现一个良好的工作和高效的数据包确认系统?

2 个答案:

答案 0 :(得分:2)

如果socket.io对您来说不够可靠,您可能需要考虑实现自己的websocket接口,而不是在socket.io上添加一个层。但要回答你的问题,我不认为运行10k计时器会是一个大问题。例如,以下代码在3秒内为我运行并打印出100000的预期结果:

var x = 0;
for (var i = 0; i < 100000; i++) {
    setTimeout(function() { x++; }, 1000);
}

setTimeout(function() { console.log(x); }, 2000);

实际上没有超时的开销;它基本上只是被放入队列,直到执行它为止。

答案 1 :(得分:1)

  

我读到如果没有时间,NodeJS将不会触发该事件。

这有点夸张,node.js计时器是可靠的。由setTimeout 设置的计时器将在某个时刻触发。如果进程在确切的预定时间忙,则可能会延迟,但最终将调用回调。

引自Node.js docs for setTimeout

  

可能不会在精确延迟的毫秒内调用回调。 Node.js不保证回调何时触发的确切时间,也不保证它们的排序。回调将尽可能接近指定的时间调用。