Node.js:在集群中有不同代码的工人?

我在node.js中有一个应用程序

此应用程序分为3个部分:

launcher.js,启动另外两个部分,并在处理清理后重新启动崩溃/更新。

app.js,在电脑上工作。

用于访问日志和不同命令的server.js。

发射器的简化代码是:

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(); } 

集群的好处是,它们和启动程序处于同一个进程中,所以我可以处理一些错误,而不必重新启动应用程序(只需调用应用程序内部的正确函数来进行“软重启”),并保持一切都在同一个过程中。

虽然与exec,我坚持重新启动服务器,有时不知道出了什么问题,这意味着有一个subshel​​l,我不喜欢。

有没有办法分叉群集,但开始一个不同的代码?

我的解决办法是:

 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 } } 

一个更有活力的例子:

 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; } 
 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(); }); } 

它适用于启动两个不同的群集,但我坚持重新启动应用程序。


编辑:最后的代码,与工作重新启动:

 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); } } 

您将需要将群集的代码存储在不同的文件中,并以该文件的path作为参数来启动此代码。