实施通用长轮询

时间:2013-03-03 21:04:19

标签: node.js long-polling

我一直在尝试实现一个简单的长轮询服务,以便在我自己的项目中使用,如果成功,可能会将其作为SAAS发布。这是我到目前为止尝试的两种方法,都使用Node.js(在后面轮询PostgreSQL)。

1。定期检查同一时间间隔内的所有客户端

每个新连接都被推送到一个连接队列中,这个连接正在间隔中传播。

var queue = [];

function acceptConnection(req, res) {
  res.setTimeout(5000);
  queue.push({ req: req, res: res });
}

function checkAll() {
  queue.forEach(function(client) {
    // respond if there is something new for the client
  });
}

// this could be replaced with a timeout after all the clients are served
setInterval(checkAll, 500);

2。单独检查每个客户端

每个客户都有自己的ticker来检查新数据

function acceptConnection(req, res) {
  // something which periodically checks data for the client
  // and responds if there is anything new
  new Ticker(req, res);
}

虽然这可以降低每个客户端的最小延迟,但它也会通过设置大量超时来引入开销。

结论

这两种方法都很容易解决问题,但我不认为这会轻易扩展到1000万个开放连接,特别是因为我在每个客户端的每次检查中轮询数据库。

我想在没有数据库的情况下这样做,只是立即向所有打开的连接广播新消息,但是如果客户端的连接在广播发生时死了几秒钟,那将会失败,因为它不是持久性的。这意味着当客户端第一次轮询时,我基本上需要能够在历史记录中查找消息。

我想这里的一步就是拥有一个数据源,我可以在其中订阅新的数据(CouchDB更改通知?),但也许我在这里忽略了一些大事?

进行高度可扩展的长轮询的常用方法是什么?我并没有特别绑定Node.js,我实际上更喜欢任何其他建议,并提出推理原因。

2 个答案:

答案 0 :(得分:0)

不确定这是否回答了您的问题,但我喜欢PushPin(+ explanation of concepts)的方法。

我喜欢这个想法(使用反向代理并与返回代码进行通信+延迟的REST返回请求),但我对实现有所保留。我可能低估了这个问题,但在我看来,使用的技术有点过分。不确定我是否会使用它,更喜欢更轻量级的解决方案,但我发现这个概念非常出色。

很想听到你最终使用的内容。

答案 1 :(得分:-1)

既然你提到了可扩展性,我必须得到一点理论,因为唯一的实际措施是负载测试。因此,我所能提供的只是建议。

一般来说,每次使用任何东西都不利于可扩展性。特别是每次连接一次或每次请求一次,因为这会使您的应用程序的一部分与流量成比例。 Node.js使用其单线程异步I / O模型删除了每个连接的线程依赖性。当然,你不能完全消除每个连接的东西,比如请求和响应对象以及套接字。

我建议避免为每个HTTP连接打开数据库连接的任何内容。这就是连接池的用途。

至于在上面两个选项之间进行选择,我个人会选择第二个选项,因为它会保持每个连接的隔离。第一个选项使用循环连接,这意味着每个连接的实际执行时间。鉴于I / O是异步的,但是在每次连接迭代和仅存在每个连接的对象之间做出选择时,我可能没有什么大不了的,我宁愿只有一个对象。然后我不用担心什么时候突然有10,000个连接。

C10K问题似乎是一个很好的参考,尽管这是个人的判断,说实话。

http://www.kegel.com/c10k.html

http://en.wikipedia.org/wiki/C10k_problem