【问题标题】:Node.js, multi-threading and Socket.ioNode.js、多线程和 Socket.io
【发布时间】:2012-01-23 16:55:53
【问题描述】:

我希望 Socket.io 在 Node.js v.0.6.0 及更高版本中使用native load balancing(“集群”)进行多线程工作。

据我了解,Socket.io 使用 Redis 来存储其内部数据。我的理解是:我们不想为每个工作人员生成一个新的 Redis 实例,而是要强制工作人员使用与主服务器相同的 Redis 实例。因此,连接数据将在所有工作人员之间共享。

master 里面是这样的:

RedisInstance = new io.RedisStore;

我们必须以某种方式将RedisInstance 传递给工作人员并执行以下操作:

io.set('store', RedisInstance);

this implementation 使用旧的第 3 方集群模块的启发,我有以下非工作实现:

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  var sio = require('socket.io')
  , RedisStore = sio.RedisStore
  , io = sio.listen(8080, options);

  // Somehow pass this information to the workers
  io.set('store', new RedisStore);

} else {
  // Do the work here
  io.sockets.on('connection', function (socket) {
    socket.on('chat', function (data) {
      socket.broadcast.emit('chat', data);
    })
  });
}

想法?我可能完全走错了方向,任何人都可以指出一些想法吗?

【问题讨论】:

  • 我想知道你最终使用的是什么方法。

标签: javascript node.js socket.io


【解决方案1】:

其实你的代码应该是这样的:

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  var sio = require('socket.io')
  , RedisStore = sio.RedisStore
  , io = sio.listen(8080, options);

  // Somehow pass this information to the workers
  io.set('store', new RedisStore);

  // Do the work here
  io.sockets.on('connection', function (socket) {
    socket.on('chat', function (data) {
      socket.broadcast.emit('chat', data);
    })
  });
}

另一种选择是打开 Socket.IO 以侦听多个端口并拥有类似 HAProxy 负载平衡的东西。 无论如何,您知道最重要的事情:使用 RedisStore 在进程之外进行扩展!

资源:

http://nodejs.org/docs/latest/api/cluster.html
How can I scale socket.io?
How to reuse redis connection in socket.io?
Node: Scale socket.io / nowjs - scale across different instances
http://delicious.com/alessioaw/socket.io

【讨论】:

  • 该实现不会为每个工作人员创建一个新的 RedisStore 吗?另外,使用像 HAProxy 这样的东西有什么好处?似乎使用 Node 中原生的功能更好。
  • HAProxy 的优点:您可以在不同的端口上拥有进程,您可以更仔细地监控它们并在它们死亡时重新启动(使用monit,upstart)。同样是的,您需要为每个工作人员创建一个新的 RedisStore。认为集群是 child_process.fork() 之上的实现,所以你基本上复制了应用程序 N 次(据我所知,进程共享相同的文件描述符)。
  • 我刚刚尝试了您的代码示例,似乎无法正常工作。单线程时,1500 个连接运行高达 50% 的 CPU(每个工作人员的工作量都比示例中的多)。使用您的示例,在 每个 进程运行高达 80-90% 的 CPU 之前,我无法获得多达 500 个连接。很明显,有些地方出了问题,因为这使情况变得更糟。
  • 这里有一个带有 child_process.fork() 的示例应用程序:github.com/dshaw/talks/tree/master/2011-10-jsclub/sample-app 你也可以尝试一下并告诉我它是怎么回事吗?基本上把worker js 代码放在app.js 那里,并尝试遵循相同的结构。
  • 啊,谢谢你的链接。理想情况下,这应该只在一个端口上工作(而不是几个,就像这个 repo 所做的那样)。有什么建议?看来我们可以使用 socket-io-announce 在所有工作人员之间共享 Redis 连接详细信息。
猜你喜欢
  • 1970-01-01
  • 2016-11-08
  • 1970-01-01
  • 1970-01-01
  • 2011-09-08
  • 2017-01-05
  • 2013-05-27
  • 2012-06-04
  • 1970-01-01
相关资源
最近更新 更多