如何在没有 redis 的情况下扩展 socket.io

fra*_*erm 2 node.js express socket.io

我目前正在寻找一种替代方案来使用 socket.io 扩展我的 Express 应用程序。问题是我不想使用 redis 作为 socket.io 存储。除了Clusterhub之外,还有其他可能性来集群 socket.io 吗?

编辑:我尝试使用fakeredis作为 redis 的替代品,但它似乎不适用于 socket.io。从ActionHero.js我知道 faye-websocket 可以与 fakeredis 配合使用。

Jos*_*llo 5

这很可能取决于您的 socket.io 使用情况以及您想要实现的扩展类型(集群与扩展到多台机器)。

因此,这就是我将 socket.io 的使用扩展到多个服务器所做的事情。

我们在负载均衡器后面有 3 个服务器,当套接字连接时,它会连接到 3 个服务器中的任何一个,这三个服务器在内存中有一个套接字列表,并且这三个服务器有一个内部服务器地址的顺序列表,例如 [server1,服务器2,服务器3]。

我所做的基本上是一个环(在内部我们称之为“套接字环”):

  • 如果我需要从 server1 向套接字发出事件,我首先查看套接字是否连接到该 server1,如果没有,我将向下一个服务器(server2)发送 http 请求,该服务器将检查套接字是否存在,如果不存在在那里它将向 server3 发送相同的请求,依此类推,直到到达原点,在这种情况下您可能会抛出错误。
  • 如果我需要广播消息,它几乎是相同的,我从一台服务器开始,然后调用其他服务器上的 http 端点。

我用来确定下一个节点(next_node.js)的算法是:

var nodes = process.env.NODES.split(',');
//this is usually:  http://server1/,http://server2/,http://server3/

var url = require('url');
var current = require("os").hostname();

//origin is the node that started the lookup
exports.get = function (origin) {
  var next_node_i = nodes.map(function (uri) {
    return url.parse(uri).hostname;
  }).reduce(function (prev, curr, i, arr){
    return curr === current && i < arr.length - 1 ? i + 1 : prev;
  }, 0);

  var next_node = nodes[next_node_i];

  if (origin && url.parse(next_node).hostname === origin) {
    // if the next node is equal to the first node initiating the lookup
    // it means the socket we are looking for is not connect to any node.
    return null;
  }

  return next_node;
};
Run Code Online (Sandbox Code Playgroud)

注意事项:

  • 这些服务器之间的延迟很低,并且网络分区不太可能,它们物理上位于同一数据中心。但如果是网络分区对我们来说就没那么重要了。
  • 我们总是朝同一个方向跑环。改进的版本将是双向运行(?)
  • 服务器共享一个秘密来调用这些端点。

在我看来,这是在许多 socket.io 用例中实现扩展的一种非常简单的方法,可能在很多其他场景中这不是一个选项,但我希望这能提供一些想法。