Skip to content

Instantly share code, notes, and snippets.

@sansmischevia
Last active August 29, 2015 14:26
Show Gist options
  • Save sansmischevia/62443f9ce07cf47aff7c to your computer and use it in GitHub Desktop.
Save sansmischevia/62443f9ce07cf47aff7c to your computer and use it in GitHub Desktop.
Cluster script that I wrote for both Vungle and Webflow to cluster node apps. This code is running on hundreds of nodes with no issues. Supports worker disconnect timeout and a daily process restart as well.
var cluster = require('cluster');
var os = require('os');
var http = require('http');
var workers = [];
var startCount = 0;
var TIMEOUT = 10000; // Wait 10 seconds for workers to disconnect
var RESTART = 86400000; // 24 hours
var intervalId;
function initInt() {
clearInterval(intervalId);
intervalId = setInterval(function () {
console.log("Restarting...");
process.kill(process.pid, "SIGUSR2");
}, RESTART);
}
if (cluster.isMaster) {
console.log('Master starting... CPUs: %d', os.cpus().length);
os.cpus().forEach(function() {
workers.push(cluster.fork());
});
initInt();
process.on('SIGUSR2',function() {
console.log("Got SIGUSR2 with " + workers.length + " workers");
initInt();
// Blank the worker list, but keep a copy for ourselves:
var copyWorkers = workers.slice();
workers = [];
copyWorkers.forEach(function (worker) {
console.log("Disconnecting " + worker.id);
worker.disconnect();
var savedTimeout = setTimeout(function () {
console.log(worker.id + " not responding, destroying.");
worker.forced_death = true;
worker.destroy();
clearTimeout(savedTimeout);
}, TIMEOUT);
worker.on('disconnect', function () {
if (worker.forced_death) {
console.log("Forced death on disconnect " + worker.id);
return;
}
console.log(worker.id + " done.");
worker.destroy();
clearTimeout(savedTimeout);
});
var newWorker = cluster.fork();
console.log('Pushing new worker: ' + newWorker.id);
workers.push(newWorker);
});
});
cluster.on('exit', function(worker, code, signal) {
console.log('worker exit:', worker.id, code, signal);
if (worker.suicide) {
console.log('exit - suicided worker: ' + worker.id);
return;
}
workers = workers.filter(function(existingWorker) {
return existingWorker.id !== worker.id;
});
if (!worker.reloaded) {
var newWorker = cluster.fork();
console.log(worker.id + ' died - forking to: ' + newWorker.id);
workers.push(newWorker);
}
});
} else {
console.log('worker #' + cluster.worker.id + ' starting...');
var server = require('./server');
server.listen(3000);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment