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

if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`);

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

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker ${worker.process.pid} died`);
  });
} else {
  // Workers can share any TCP connection
  // In this case it is an HTTP server



  var sticky = require('sticky-session');
  var express = require('express');
  var app = express();

  app.get('/', function (req, res) {
      console.log('worker: ' + cluster.worker.id);
      res.send('Hello World!');
  });


  var server = http.createServer(app);
      sticky.listen(server,3000);

  console.log(`Worker ${process.pid} started`);
}

nodejsクラスタリングとスティッキーセッションのドキュメントと、これに関する別のスタックオーバーフローの回答を調べました

  var cluster = require('cluster');
  var http = require('http');
  var sticky = require('sticky-session');
  var express = require('express');
  var app = express();

  app.get('/', function (req, res) {
      console.log('worker: ' + cluster.worker.id);
      res.send('Hello World!');
  });


  var server = http.createServer(app);
      sticky.listen(server,3000);

上記のスニペットが fork せずに実行された場合は正常に動作しますが、スレッドが開始されてもサーバーが初期化されない上記のクラスター化された例に示されているように動作しません。

スティッキークラスターの代替手段があることを読みました。誰かがこのトピックについて適切な信頼できる回答を与えることができます。これは、同じものを探している人にとって役立ちます。これに伴う別の主な問題は、変数を保存するために使用される app.locals オブジェクトです。アプリインスタンスと複数のサーバーインスタンスが発生すると、インスタンスごとに値が異なるため、これが壊れます。このアプローチは大きな問題を引き起こし、アプリが壊れます。答えるときは、コードをコピーして貼り付けないでください。その利点と欠点にアプローチします。

sticky-sessions nodejs モジュールの使用に限定された答えを探しているわけではありません。プロセッサのすべてのコアが使用され、セッションの継続性が保証される他のすべてのアプローチを歓迎します。

RedisStore や MongoDb ストアが関係する場合は問題ありません。知りたいのは、セッション継続性を備えたクラスタリングを使用する nodejs アプリケーションの場合の標準的なアプローチについてです。

https://github.com/indutny/sticky-session

https://nodejs.org/api/cluster.html

https://stackoverflow.com/a/37769107/3127499

4

3 に答える 3

3

コードに小さな問題があります。「sticky-session」モジュールは、すでに node.js の「cluster」モジュールを使用しています。「fork()」は、 sticky-session が既に行っているため、必要ありません。方法を見てみましょう:

var cluster = require('cluster'); // Only required if you want the worker id
var sticky = require('sticky-session');

var server = require('http').createServer(function(req, res) {
  res.end('worker: ' + cluster.worker.id);
});
sticky.listen(server, 3000);

sticky.listen() を呼び出すと、すでにワーカーが生成されます。以下の listen() 実装を参照してください。

 function listen(server, port, options) {
  if (!options)
    options = {};

  if (cluster.isMaster) {
    var workerCount = options.workers || os.cpus().length;

    var master = new Master(workerCount, options.env);
    master.listen(port);
    master.once('listening', function() {
      server.emit('listening');
    });
    return false;
  }
  return true;
}

この行 var master = new Master(workerCount, options.env) は、ワーカーの生成を担当します。以下の Master() 実装を参照してください。

function Master(workerCount, env) {
  net.Server.call(this, {
    pauseOnConnect: true
  }, this.balance);

  this.env = env || {};

  this.seed = (Math.random() * 0xffffffff) | 0;
  this.workers = [];

  debug('master seed=%d', this.seed);

  this.once('listening', function() {
    debug('master listening on %j', this.address());

    for (var i = 0; i < workerCount; i++)
      // spawning workers
      this.spawnWorker();
  });
}

したがって、実際に sticky.listen(server,port) を呼び出すときは、実際には cluster.fork(). を呼び出していることになります。したがって、明示的に再度 fork() を呼び出すべきではありません。コードは次のようになります。

var cluster = require('cluster'); // Only required if you want the worker id
var sticky = require('sticky-session');

var server = require('http').createServer(function(req, res) {
  res.end('worker: ' + cluster.worker.id);
});

//sticky.listen() will return false if Master
if (!sticky.listen(server, 3000)) { 
  // Master code
  server.once('listening', function() {
    console.log('server started on 3000 port');
  });
} else {
  // Worker code
}

覚えておくべき重要なことの 1 つは、生成されたワーカーには独自のEVENTLOOPメモリがあるため、リソースが互いに共有されないことです。「REDIS」または「memored」などの他の npm モジュールを使用して、異なるワーカー間でリソースを共有できます。

これで両方の問題が解決することを願っています。

于 2018-07-19T09:07:18.703 に答える