簡體   English   中英

在Heroku上使用cluster和socket.io-redis擴展node.js socket.io@1.*.*

[英]Scale node.js socket.io@1.*.* with cluster and socket.io-redis on Heroku

有誰知道一個很好的解決方案,可以在多個內核上擴展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

當前,在分支feature/sticky還有一個使用sticky-session的實現似乎更好地工作。

最后,該應用程序需要發布到Heroku ,並在多個dyno上進行縮放。

最初,我嘗試執行類似的操作-僅為群集節點啟動服務器,但始終收到錯誤消息: 失敗:在收到握手響應之前連接已關閉

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();
}

然后,我也嘗試為主節點啟動服務器:

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();
}

我還在分支feature/sticky同時使用了sticky-sessionsocket.io-redis進行了嘗試,這似乎很成功,但似乎仍然不是一個好的解決方案:

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');
  });
}

接下來的幾天我將做更多測試,但是,如果有人可以提出一些想法,這將對您有很大幫助。

謝謝,

您可能正在尋找socket.io-redis。 http://socket.io/blog/introducing-socket-io-1-0/ (滾動到“可擴展性”)

這是有關如何使用socket.io + express創建腳手架的簡短示例:

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具有pub / sub,並且所有socket.io節點都需要訂閱redis才能從通道獲取所有消息。 這樣,一個進程可以將消息廣播到通道(發布),而所有其他進程以最小的延遲接收消息,以將消息廣播到其連接的客戶端(訂閱)。 您甚至可以使用基於Redis的會話來擴展它。

我認為您所指的集群模塊有點誤導。 據我所知,它有助於創建單個子流程,但不會“同步”多個節點之間的通道。 如果您的客戶不需要與他人交流,那就很好。 如果要向所有節點上的所有已連接客戶端廣播消息,則需要redis模塊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM