【问题标题】:Scaling Engine.IO with a Redis Store (vs. Socket.IO)使用 Redis 存储扩展 Engine.IO(与 Socket.IO 相比)
【发布时间】:2013-08-09 10:12:15
【问题描述】:

关于这个主题有几个问题,但没有一个能完全解决这个问题。

我正在使用带有 redis 存储的 Socket.IO,我正在为流量增加做准备。我的托管公司说,“你需要使用 Engine.IO 而不是 Socket.IO,因为它更有效”,所以我正忙着弄清楚这意味着什么。

Questions like this 的答案看似矛盾:

所以我的看法:

  • Socket.IO 0.9 降级
  • Engine.IO 增强
  • Socket.IO 1.0 将使用 Engine.IO
  • 如果要在多个实例上运行 Engine.IO,则必须自己编写 redis 存储

但随后Engine.IO 说它是“负载均衡器友好的”,但对 redis 只字未提。它必须有某种外面的商店,对吧?但是如果它有多个传输和一个存储,那么 Socket.IO 有什么意义呢?

然后我看到 Socket.IO might be abandonedhigh profile companies are movingPrimus

如何扩展 Engine.IO?我必须自己编写存储吗?

【问题讨论】:

  • 如果您使用 Engine.IO,是的,您必须编写自己的商店。我知道抱怨开源项目缺乏更新并不酷,但我觉得他们在 Socket.IO 上丢了球。像这样的问题很多,而 1.0 已经指日可待了半年多。 socket.io 上有数百个存在数月之久的未解决问题,因此它在这一点上给人以无人维护的所有外观。
  • 如果你想使用engine.io 那么是的,你必须编写额外的东西。我可以想象 socket.io 面临一些适应新内核的障碍。 socket.io 是向engine.io 表示要连接的东西。它隐藏了engine.io的底层细节,灵活且用户友好。但是出于同样的原因,我会要求您不要在其上建立商店。 socket.io 1.0 是基于 engine.io 的承诺而构建的。鉴于 socket.io 1.0 的状态,任何人都可以保证 engine.io 会成功。如果 1.0 正在准备中,请等待它,因为它会比你能做的更好,如果它来了。

标签: node.js socket.io


【解决方案1】:

好吧,正如你自己提到的,我应该看看 Primus。使用 HAProxy 实现缩放。 作为底层通信,你仍然可以使用 Socket.io,也可以使用 engine.io。通过使用 Primus,您可以试验不同的库。 http://pusher.com/docs/server_libraries 有一篇关于 Redis 伸缩的有趣文章。

【讨论】:

  • 请记住,它推荐 HAProxy 用于其粘性会话,这意味着它应该始终将具有相同会话的人重定向到同一台机器。它这样做代替了连接信息的公共存储。每种方法都有一些优点和缺点,因此请确保在做出决定之前了解这些优点和缺点。 stackoverflow.com/questions/1553645/…
  • 我没有决定。我只是想帮助并将 OP 指向其他人写的一些文章。感谢您降级。
  • 我知道。那是为 OP 设计的。
【解决方案2】:

只是想分享我在上周学到的东西,但希望其他人能来并明确回答这个问题,以便我可以给他们检查。

1) 永远不要使用 Socket.IO(截至 0.9.16)

我的主人告诉我使用 Engine.IO(或其他任何东西)是正确的。 Socket.IO 有大量的重大问题,其中最糟糕的是它会意外DDoS your server。我在客户端相对较少的情况下亲身体验了这一点,它完全禁用了我的服务器,直到我可以重写 Socket.IO。我扩大到 25 多架无人机来吸收打击,这没关系。单个客户端每秒可以发送 1000 个请求。

2) 其他引擎没有 Redis 存储

Socket.IO 允许您通过放入节点的 Redis 存储进行跨节点广播。据我所知,Engine.IO、Primus 和 SockJS 不提供此功能。因此,当这些引擎声称“负载均衡器”友好时,并不意味着您可以跨节点广播。我开始认为这实际上是一件好事。使用 redis 编写 pub/sub 相对容易,将其分离出来也很好。

我最终使用PrimusEngine.IO,然后使用redis pub/sub 在节点之间共享事件。我花了大约 5 个小时来删除 Socket.IO、连接 Primus、编写 pub/sub 并上线。到目前为止,这是一次更好的体验。

更新:

最终 Engine.IO 也进入了重新连接循环(每秒几个),所以我最终使用了 SockJS。它给了我最好的连接性和稳定性,以及Primus now handles the reconnect(SockJS 没有这样做)。

【讨论】:

  • 嘿,现在您从引擎切换到 sockjs,redis pub/sub 仍然可以正常工作吗?你仍然可以使用 redis 进行扩展吗?
  • 需要明确的是,Redis pub/sub 没有内置在 engineio 或 sockjs 中。我完全独立地连接了redis。由于我使用的是 Primus,因此切换根本没有改变 redis 部分。
  • 为什么不使用 Primus + Redis pub/sub 并添加 SockJs 层?
  • 单个套接字 io 客户端每秒可以发送数千个请求,为什么不简单地创建一个时间变量来存储此套接字上次发送请求的时间,如果它小于一毫秒前例如,然后这个套接字正在发送垃圾邮件并将其断开。或者您知道,任何其他类似于阻止垃圾邮件套接字和滥用用户的自定义检查。除非我误解了你的 socket io 问题...
【解决方案3】:

我同意在 v1.0 发布之前应该避免使用 Socket.IO,它有问题并且在我的测试中 Engine.IO 表现更好(https://medium.com/node-js-javascript/b63bfca0539)。 Primus 也绝对是一个不错的选择:也许您现在会使用 Engine.IO,但是当 Socket.IO 1.0 发布时,您会想要切换到它。

我用 Engine.IO 和 Redis 和 Pub/Sub 结构实现了一个类似的程序,它看起来非常优雅。下面的代码将连接的客户端订阅到房间/频道。

io.on('connection', function (socket) {
  var observerRedisClient = redis.createClient();
  observerRedisClient.subscribe(resourceId, redis.print);

  observerRedisClient.on('message', function(channel, message) {
      socket.send(message);
  });
});

如果您更新该频道,即。保存一些数据并发布,然后所有订阅的客户端都会收到它。

redisClient.set(key, value, redis.print);
redisClient.publish(key, value);

如果你有兴趣代码是开源的:https://github.com/denizozger/node-engine.io-server

【讨论】:

    猜你喜欢
    • 2012-08-16
    • 2016-03-16
    • 2014-03-06
    • 2012-03-25
    • 2012-09-17
    • 2015-02-09
    • 2014-11-25
    • 1970-01-01
    • 2015-05-04
    相关资源
    最近更新 更多