I have been using redis as an in-memory store with my nodejs server.
Sessions are also being managed with redis.
Currently what i have been doing is, i flush my redis whenever my server connects to it, so that no session is there whenever server starts
Like this:
redisClient.on('connect', function () {
redisClient.flushdb(function (err, succeeded) {
logger.debug("redis db cleared on startup--", succeeded); // will be true if successfull
});
});
I also use redis for some other data storage like some queue.
But now i want to implement clustering on my server.
My problem is if i have 4 cores, 4 instances of node will be runnig on my server.
num_processes = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
var workers = [];
// Helper function for spawning worker at index 'i'.
var spawn = function(i) {
console.log("spawing at index---",i);
workers[i] = cluster.fork();
console.log("----worker id-------", workers[i].id,"-------");
// Optional: Restart worker on exit
workers[i].on('exit', function(code, signal) {
console.log(`code is ${code} and signal is ${signal}`)
console.log(`worker ${workers[i].process.pid} died array index is ---${i}`);
console.log('respawning worker', i);
spawn(i);
});
workers[i].on('listening', () => {
workers[i].send({'index' : i });
});
};
// Spawn workers.
for (var i = 0; i < num_processes; i++) {
spawn(i);
} // Code to run if we're in a worker process
} else {
var redis = require('redis');
const sio_redis = require('socket.io-redis'),
redisClient = redis.createClient();
redisClient.on('connect', function () {
redisClient.flushdb(function (err, succeeded) {
logger.debug("redis db cleared on startup--", succeeded); // will be true if successfull
});
});
var RedisStore = require('connect-redis')(session);
const redisStore = new RedisStore({'host': 'localhost', 'port': 6379, 'client': redisClient});
var server = require('http').Server(app);
var listeningServer = server.listen(3002);
}
If any instance exit or die due to some reason , it will clear all the session and data in redis
I dont want this to happen. How should i work with redis in this scenario, so that sessions and data corresponding to that instance get cleared?
You can check if current process is master. That way it will only flush the first time you start your app. If any fork restarts then it wont flush the db.
redisClient = redis.createClient();
redisClient.on('connect', function() {
if (cluster.isMaster) {
redisClient.flushdb(function(err, succeeded) {
logger.debug("redis db cleared on startup--", succeeded); // will be true if successfull
});
}else{
logger.debug("Forked instance no need to flush redis db"); //
}
});
There are essentially two ways around this that I think are sane:
You say you want to cleanup session data on startup. Well, one of the points of having sessions not in memory is to persist them accross the sessions, and keep your actual app server (Node.js app) stateless.
You can, e.g. set expire key on all session data. So every time you "save" a session, you also setex on that session, optionally even prolonging this TTL every time you access the session (so, a session is valid 12 hours from last touching it, or something). Or, depending on your usage, your session middleware could do that, e.g. https://stackoverflow.com/a/45019589/162070.
Or not expire it at all.
Maybe you only flush sessions because you expect to have breaking changes and your old sessions won't work. Or have an explicit requirement, that on each new deploy, you clean the session data up. In any case, you separate this then. Have, for example, your server.js, as your app, and have a separate session-cleanup.js file that connects to redis, flushes, and disconnects. Then have npm setup like this:
"scripts": {
"session.cleanup": "node lib/session-cleanup.js",
"start": "npm run session.cleanup && node lib/server.js",
...
}
That way, before running your server.js and it runs cluster mode, you will cleanup sessions first. And if your cluster instances die and respawn, nothing happens.
Now, each time you redeploy, you clean it up. Or even remove this from "start", and have your deployment pipeline call npm run session.cleanup explicitly. You can even expose a button in an admin UI to do this on runtime (which would likely log you out :)), the point is, session cleanup is now a separate issue from server start.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With