Node.js: Worker with different code in a cluster?

I have an application in node.js.

This application is divided into 3 parts:

launcher.js, which start the other two parts and restart them when it fails / updates after cleaning processing.

app.js that themselves work on the computer.

server.js, which is used to access the log and other command.

Simplified code to run:

var cluster = require('cluster'), exec = require('child_process').exec, server; if (cluster.isMaster) { cluster.fork(); server = exec('server.js'); cluster.on('exit', function(worker, code, signal) { //Clean corrupted data, log crash if neccessary, reload source code for update ... cluster.fork(); }); server.on('exit', function () { //Same as for app, with a different handling of signal... server = exec('node server.js'); }); } else { var self = require('app.js); self.start(); } 

The good thing with the cluster is that they are in the same process as in Launcher, so I can deal with some error without restarting the application (just calling the correct function inside the application for a β€œsoft restart”), and keep everything in one process.

While with exec, I was stuck in restarting the server, once not knowing what went wrong, and that means having a subshell, which I don't like.

Is there a way to unlock the cluster, but start a different code?

+6
source share
2 answers
 var cluster = require('cluster'); if (cluster.isMaster) { var app = cluster.fork(), server = cluster.fork(); app.on('message', function () { app.send('app'); }); server.on('message', function () { server.send('server'); }); } else { process.send(''); process.on('message', function (code) { var self=require('/path/to/' + code + '.js'); self.start(); }); } 

It works to run two different clusters, but I am stuck in restarting the application.


EDIT: final code with working restart:

 var VERSION = 0.3, util = require('util'), cluster = require('cluster'), PATH = process.argv[1].substr(0, process.argv[1].lastIndexOf('/') + 1), lib = [], childs = []; function listen(child, i) { child.on('message', function(m) { if (m.type === 'REBOOT') { reboot(); } else if (m.type === 'CODE1') { child.send({type: 'START', c: lib[i]}); } else { log('ERROR', ''); } }); child.on('exit', function(worker, code, signal) { delete require.cache[require.resolve(PATH + lib[i])]; childs[i]=cluster.fork(); listen(childs[i], i); }); } function reboot() { i = 0; do { childs[i].kill(); i = i + 1; }while (i < childs.length); } if (!cluster.isMaster) { var self; process.send({type:'START'}); process.on('message', function(m) { if (m.type === 'START'){ self = require(PATH + mc); self.start(); } }); } else { var i = 3; if (process.argv.length < 4) { log('ERROR', 'Not enought argument'); log('USAGE', 'node launcher.js x ...'); log('USAGE', '...: Apps to start (at least one)'); process.exit(-1); } else { do { lib.push(process.argv[i]); i = i + 1; }while (i < process.argv.length); i = 0; do { childs.push(cluster.fork()); i = i + 1; }while(i < lib.length); i = 0; do { listen(childs[i], i); i = i + 1; }while(i < lib.length); } } 

You need to store the cluster code in different files and run this code using the file paths as arguments.

+2
source

My decision:

 var cluster = require("cluster"); if(cluster.isMaster){ // Forking Worker1 and Worker2 var worker1 = cluster.fork({WorkerName: "worker1"}); var worker2 = cluster.fork({WorkerName: "worker2"}); // Respawn if one of both exits cluster.on("exit", function(worker, code, signal){ if(worker==worker1) worker1 = cluster.fork({WorkerName: "worker1"}); if(worker==worker2) worker2 = cluster.fork({WorkerName: "worker2"}); }); } else { if(process.env.WorkerName=="worker1"){ // Code of Worker1 } if(process.env.WorkerName=="worker2"){ // Code of Worker2 } } 

A more dynamic example:

 var cluster = require("cluster"); if(cluster.isMaster){ // Forking Workers based on args if(process.argv.length < 3){ console.log("Usage: "+process.argv[1]+" module [module]"); } process.argv.forEach(function (val, index, array) { // Don't use this script as worker (index 1 = self) if(index>1){ // Resolve the module before spawning to prevent loop. try { require.resolve(val); spawn(val); } catch(e) { console.error("Module '"+val+"' not found"); } } }); cluster.on("exit", function(worker, code, signal){ respawn(worker); }); } else { var self = require(process.env.WorkerScript); self.start(); } function spawn(script){ cluster.fork({WorkerScript: script}).env = {WorkerScript: script}; } function respawn(worker){ console.log("Respawning: "+worker.env.WorkerScript) cluster.fork(worker.env).env = worker.env; } 
+13
source

All Articles