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);如果上面的代码片段是在没有works的情况下运行的,那么它工作得很好,否则就不会像上面的集群示例中所示的那样工作,在该示例中,线程被启动,但服务器永远不会初始化。
我读到有粘性集群的替代方案,有人可以在这个话题上给出一个适当的权威答案,这对寻找相同的人很有用,另一个主要问题是app.locals对象,它用于存储应用程序实例的变量,多个服务器实例的出现会导致这个问题,因为不同实例的值会不同,所以这种方法会导致一个大问题和应用程序中断,所以.When回答请不要复制粘贴一些代码,请给出一个详细的答案,详细说明它的优点和缺点。
我不是在寻找一个仅限于使用粘性会话nodejs模块的答案,我欢迎所有其他方法,其中使用处理器的所有核心,但确保会话连续性。
如果涉及到RedisStore或MongoDb存储,我想知道的是在使用具有会话连续性集群的nodejs应用程序的情况下的标准方法。
https://github.com/indutny/sticky-session
发布于 2018-07-19 17:07:19
您的代码中有一个小问题。"sticky-session“模块已经使用了node.js”集群“模块,within.You不需要"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(server, 3000);调用sticky.listen()将已经为下面的you.See ()实现产生监听的工作进程
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(服务器,端口)时,您实际上是在调用fork() fork(),您不应该再次显式地调用cluster.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
}需要记住的重要一点是,生成的工作线程将拥有自己的事件日志和内存,因此资源不会相互共享。您可以使用"REDIS“或其他npm模块(如"memored”)在不同的worker之间共享资源。
希望这能解决你的两个问题。
发布于 2019-09-22 14:06:53
我认为你混淆了sticky session和共享内存存储。
让我试着帮你:
实现粘性会话意味着现在有多个节点接受连接。但是,它不能保证这些节点将共享相同的内存,因为每个worker都有自己的eventloop和内部内存状态。
换句话说,一个节点正在处理的数据可能对其他工作节点不可用,这就解释了您指出的问题。
...another的主要问题是app.locals对象,该对象用于存储应用程序实例的变量,多个服务器实例的出现会导致该对象崩溃,因为不同实例的值将不同,因此这种方法会导致一个大问题和应用程序中断……
因此,为了解决这个问题,我们需要使用像Redis这样的东西,以便数据可以在多个节点之间共享。
希望这能有所帮助!
发布于 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://www.npmjs.com/package/jsonwebtoken
https://cloud.google.com/iot/docs/how-tos/credentials/jwts#iot-core-jwt-refresh-nodejs
https://stackoverflow.com/questions/51301126
复制相似问题