2013-12-13 32 views
6

我在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,我不喜歡。

有沒有辦法分叉羣集,但啓動不同的代碼?

回答

2
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 + m.c); 
      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); 
    } 
} 

你就需要存儲集羣的代碼在不同的文件,並與路徑的文件作爲參數啓動這個代碼。

+0

你爲什麼包括'需要( 'child_process')EXEC;'在第一個代碼示例?我沒有看到你在哪裏使用這個地方 – qodeninja

+0

@qodeninja:錯誤whenb最小化示例,它在代碼中稍後使用,但不是爲此,感謝您指出此:)) – DrakaSAN

13

我解決了這個:

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; 
} 
+0

尼斯,但工人數硬編碼 – DrakaSAN

+0

在這個例子中的工人數量是硬編碼的。看看我的編輯更加動態的例子。 – Wolfspirit

+0

對於動態示例,它比我自己的代碼更清潔。 – DrakaSAN