首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Sticky-Session的Nodejs集群

使用Sticky-Session的Nodejs集群
EN

Stack Overflow用户
提问于 2018-07-12 16:48:49
回答 3查看 4.3K关注 0票数 7
代码语言:javascript
复制
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集群和粘滞会话的文档,以及关于此问题的另一个堆栈溢出答案

代码语言:javascript
复制
  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);

如果上面的代码片段是在没有works的情况下运行的,那么它工作得很好,否则就不会像上面的集群示例中所示的那样工作,在该示例中,线程被启动,但服务器永远不会初始化。

我读到有粘性集群的替代方案,有人可以在这个话题上给出一个适当的权威答案,这对寻找相同的人很有用,另一个主要问题是app.locals对象,它用于存储应用程序实例的变量,多个服务器实例的出现会导致这个问题,因为不同实例的值会不同,所以这种方法会导致一个大问题和应用程序中断,所以.When回答请不要复制粘贴一些代码,请给出一个详细的答案,详细说明它的优点和缺点。

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

如果涉及到RedisStore或MongoDb存储,我想知道的是在使用具有会话连续性集群的nodejs应用程序的情况下的标准方法。

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

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

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

EN

回答 3

Stack Overflow用户

发布于 2018-07-19 17:07:19

您的代码中有一个小问题。"sticky-session“模块已经使用了node.js”集群“模块,within.You不需要"fork()”,因为粘滞会话已经为你完成了。让我们来看看是如何做到的:

代码语言:javascript
复制
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()将已经为下面的you.See ()实现产生监听的工作进程

代码语言:javascript
复制
 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()实现:

代码语言:javascript
复制
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(服务器,端口)时,您实际上是在调用fork() fork(),您不应该再次显式地调用cluster.fork()。现在,您的代码应该如下所示:

代码语言:javascript
复制
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
}

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

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

票数 3
EN

Stack Overflow用户

发布于 2019-09-22 14:06:53

我认为你混淆了sticky session共享内存存储

让我试着帮你:

  • Sticky-sessions模块正在使用其IP地址平衡请求。因此,客户端将始终连接到相同的工作服务器,socket.io将按预期工作,但在多个进程上!

实现粘性会话意味着现在有多个节点接受连接。但是,它不能保证这些节点将共享相同的内存,因为每个worker都有自己的eventloop和内部内存状态。

换句话说,一个节点正在处理的数据可能对其他工作节点不可用,这就解释了您指出的问题。

...another的主要问题是app.locals对象,该对象用于存储应用程序实例的变量,多个服务器实例的出现会导致该对象崩溃,因为不同实例的值将不同,因此这种方法会导致一个大问题和应用程序中断……

因此,为了解决这个问题,我们需要使用像Redis这样的东西,以便数据可以在多个节点之间共享。

希望这能有所帮助!

票数 2
EN

Stack Overflow用户

发布于 2018-07-24 23:15:02

如果我没记错的话,您正在处理内存中的数据存储或会话存储。这是多节点或集群中基于会话的认证中的已知问题之一。假设您对节点A进行了调用,并获得了名为sessionA的会话,但是对于下一次调用,您对节点B进行了调用。节点B对sessionA一无所知。人们试图通过使用sticky session来解决这个问题,但这还不够。好的做法是使用另一种方法,比如JWT或oAuth2。对于服务到服务的通信,我更喜欢JWT。JWT不存储任何内容,并且是无状态的。它与REST配合使用非常出色,因为REST也是无状态的。这里的https://www.rfc-editor.org/rfc/rfc7519是JWT实现的规范。如果您需要某种刷新令牌,那么您需要考虑存储。存储可以是REDIS、MongoDB或任何其他基于SQL的数据库。有关nodejs中JWT的进一步说明:

https://jwt.io/

https://jwt.io/introduction/

https://www.npmjs.com/package/jsonwebtoken

https://cloud.google.com/iot/docs/how-tos/credentials/jwts#iot-core-jwt-refresh-nodejs

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

https://stackoverflow.com/questions/51301126

复制
相关文章

相似问题

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