Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to gracefully restart a NodeJS server?

Tags:

Currently, my prod environment for a side project is a git repo, where I pull in some code, manually kill the server with Ctrl-C, and restart it manually.

I realize there are a lot of things wrong with this. For instance, what if a user is still in the middle of doing something important and the process is crunching sensitive data, and I just killed it?!

When I used node v0.4.x there was a nice Cluster module that could restart the server gracefully, when the application is in a quiet state. In v0.6.x the Cluster module is built into node, but it's really, really bare, and doesn't have the graceful restart ability.

Anyone know how I can gracefully restart a nodejs server in v0.6.x?

like image 337
user1159470 Avatar asked Jan 19 '12 21:01

user1159470


People also ask

How do I restart a node js server?

js server with nodemon. In this case, if we make any changes to the project then we will have to restart the server by killing it using CTRL+C and then typing the same command again. It is a very hectic task for the development process.

What is graceful shutdown?

A graceful shutdown is when a computer is turned off by software function and the operating system (OS) is allowed to perform its tasks of safely shutting down processes and closing connections. A hard shutdown is when the computer is forcibly shut down by interruption of power.


2 Answers

You can handle POSIX signals in node code.

See in the example code, that will handle SIGINT (Ctrl-C for instance) as a STOP signal for all cluster workers, and SIGUSR2 will just restart all workers

So, issuing kill -SIGUSR2 PID, where PID is node master PID will restart all cluster

module.exports = function(app) {     var cluster = require('cluster');     var numCPUs = require('os').cpus().length;     var workerList = new Array();     var sigkill = false;      if (cluster.isMaster) {         for (var i = 0; i < numCPUs; i++) {             var env = process.env;             var worker = cluster.fork(env);             workerList.push(worker);         }          process.on('SIGUSR2',function(){             console.log("Received SIGUSR2 from system");             console.log("There are " + workerList.length + " workers running");             workerList.forEach(function(worker){                 console.log("Sending STOP message to worker PID=" + worker.pid);                 worker.send({cmd: "stop"});             });         });          process.on('SIGINT',function(){             sigkill = true;             process.exit();         });          cluster.on('death', function(worker) {             if (sigkill) {                 logger.warn("SIGKINT received - not respawning workers");                 return;             }             var newWorker = cluster.fork();             console.log('Worker ' + worker.pid + ' died and it will be re-spawned');              removeWorkerFromListByPID(worker.pid);             workerList.push(newWorker);         });     } else {         process.on('message', function(msg) {             if (msg.cmd && msg.cmd == 'stop') {                 console.log("Received STOP signal from master");                 app.close();                 process.exit();             }         });         app.listen(3000);     }      function removeWorkerFromListByPID(pid) {         var counter = -1;         workerList.forEach(function(worker){             ++counter;             if (worker.pid === pid) {                 workerList.splice(counter, 1);             }         });     } } 
like image 185
Andriy Samilyak Avatar answered Sep 27 '22 16:09

Andriy Samilyak


There's a module named Forever.

That can gracefully restart the process. I suppose then you can somehow run several instances with cluster (one on each core) and use Forever to monitor / restart them.

This is just an option I found; I'm open to suggestions!

like image 37
user1159470 Avatar answered Sep 27 '22 17:09

user1159470