首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用集群和Heroku上的socket.io-redis缩放node.js Socket.IO@1.**

使用集群和Heroku上的socket.io-redis缩放node.js Socket.IO@1.**
EN

Stack Overflow用户
提问于 2014-09-30 14:29:16
回答 1查看 1.5K关注 0票数 6

有没有人知道一个好的解决方案,把一个基于node.js - socket.io的应用程序扩展到多个核上?我目前正在测试socket.io文档中提出的解决方案,以便在多个节点上使用socket.io,但没有取得具体的成功。

我已经在github:https://github.com/liviuignat/socket.io-clusters上创建了一个操场,它是来自socket.io站点的聊天应用程序的修改拷贝。它使用expressclustersocket.io@1.1.0socket.io-redis

目前,在分支sticky-session中也有一个使用feature/sticky的实现,它似乎工作得更好。

最后,需要将应用程序发布到Heroku,在多个dynos上进行缩放。

最初,我尝试这样做--只为集群节点启动服务器,但我总是得到错误: failed:连接在收到握手响应之前已关闭。

代码语言:javascript
复制
if (cluster.isMaster) {    
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', function(worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died');
  });
} else {
  var server = new Server({
      dirName: __dirname,
      enableSocket: true
    })
    .setupApp()
    .setupRoutes()
    .start();
}

然后,我还尝试为主节点启动服务器:

代码语言:javascript
复制
if (cluster.isMaster) {
  var server = new Server({
      dirName: __dirname,
      enableSocket: true
    })
    .setupApp()
    .setupRoutes()
    .start();

  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', function(worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died');
  });
} else {
  var server = new Server({
      dirName: __dirname,
      enableSocket: true
    })
    .setupApp()
    .setupRoutes()
    .start();
}

我还使用了sticky-sessionsocket.io-redis在分支feature/sticky中进行了尝试,这似乎成功地执行了,但仍然不是一个好的解决方案:

代码语言:javascript
复制
if (cluster.isMaster) {
  sticky(function() {
    var server = new Server({
        dirName: __dirname,
        enableSocket: true
      })
      .setupApp()
      .setupRoutes();
    return server.http;
  }).listen(3000, function() {
    console.log('server started on 3000 port');
  });

  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', function(worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died');
  });
} else {
  sticky(function() {
    var server = new Server({
        dirName: __dirname,
        enableSocket: true
      })
      .setupApp()
      .setupRoutes();
    return server.http;
  }).listen(3000, function() {
    console.log('server started on 3000 port');
  });
}

接下来的几天,我会做更多的测试,但是,如果有人能想出一些想法的话,这会有很大的帮助。

谢谢,

EN

回答 1

Stack Overflow用户

发布于 2014-09-30 14:42:37

你可能在找socket.io-redis。http://socket.io/blog/introducing-socket-io-1-0/ (滚动到“可伸缩性”)

下面是一个关于如何使用socket.io +express创建脚手架的简短示例:

代码语言:javascript
复制
var cluster = require('cluster');

var express = require('express')
    , app = express()
    , server = require('http').createServer(app);

var
    io = require('socket.io').listen(server)
    var redis = require('socket.io-redis');
    io.adapter(redis({ host: 'localhost', port: 6379 }));



var workers = process.env.WORKERS || require('os').cpus().length;

/**
 * Start cluster.
 */

if (cluster.isMaster) {

  /**
   * Fork process.
   */

  console.log('start cluster with %s workers', workers-1);
  workers--;
  for (var i = 0; i < workers; ++i) {
    var worker = cluster.fork();
    console.log('worker %s started.', worker.process.pid);
  }

  /**
   * Restart process.
   */

  cluster.on('death', function(worker) {
    console.log('worker %s died. restart...', worker.process.pid);
    cluster.fork();
  });


} else {
  server.listen(process.env.PORT || 9010);
}

Redis有发布/订阅,所有socket.io节点都需要订阅redis才能从一个通道获取所有消息。这样,一个进程就可以将消息广播到信道(发布),而所有其他进程都以最小的延迟接收消息,以便将消息广播到其连接的客户端(订阅)。您甚至可以通过基于redis的会话来扩展这一点。

在我看来,您所指的集群模块有点误导。就我所理解的概念而言,它有助于创建非虚拟子进程,但不会“同步”多个节点之间的通道。如果你的客户不需要和别人沟通,那也没关系。如果要向所有节点上的所有连接客户端广播消息,则需要redis模块。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26123355

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档