Nodejs使用Sticky-Session进行聚类

cod*_*eaK 6 node.js sticky-session node-cluster

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`);
}
Run Code Online (Sandbox Code Playgroud)

我查阅了nodejs集群和sticky-session的文档以及另一个关于此的堆栈溢出答案

  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);
Run Code Online (Sandbox Code Playgroud)

如果上面的代码片段在没有分叉的情况下运行它可以正常工作,但是其他方法永远不会像上面的集群示例中所示那样启动线程,但服务器永远不会初始化.

我读到有粘性集群的替代品可以有人给出一个关于这个主题的正确的权威答案,这对于寻找相同的人有用,而另一个主要问题来自于app.locals对象,用于存储变量一个应用程序实例和多个服务器实例的出现导致它中断,因为不同实例的值会有所不同,所以这种方法会导致一个大问题,应用程序会中断.所以请回答请不要复制粘贴一些代码请详细解答详细说明接近它的好处和缺点.

我不是在寻找仅限于使用粘性会话nodejs模块的答案,我欢迎使用处理器的所有内核并确保会话连续性的所有其他方法.

如果它涉及RedisStore或MongoDb存储它的确定,我想知道的是关于nodejs应用程序的标准方法,具有会话连续性的集群

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

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

/sf/answers/2643837521/

Vas*_*rag 4

您的代码中有一个小问题。“ 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);
Run Code Online (Sandbox Code Playgroud)

调用 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;
}
Run Code Online (Sandbox Code Playgroud)

这行 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();
  });
}
Run Code Online (Sandbox Code Playgroud)

因此,实际上,当您调用 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
}
Run Code Online (Sandbox Code Playgroud)

要记住的一件重要的事情是,生成的工作人员将拥有自己的EVENTLOOP内存,因此资源不会相互共享。您可以使用“REDIS”或其他npm模块(例如“memored”)在不同的worker之间共享资源。

希望这能解决您的这两个问题。