2013-12-13 11 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(); 
} 

クラスタと良いことは、彼らはランチャーと同じプロセスであるということですので、私はアプリを再起動せずに、いくつかのエラーを処理することができます(ただ呼び出します自己の "ソフトリブート"のためのアプリ内の適切な機能)、そしてすべてを同じプロセスに保ちます。

は幹部との間に、私はいつか何が悪かったのか知らなくても、サーバーの再起動で立ち往生M、そしてそれは私が嫌いサブシェルを有することを意味します。

異なるコードをクラスタをforkが、起動する方法はありますか?

答えて

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

これは2つの異なるクラスタを起動するために機能しますが、アプリの再起動時に停止します。


EDIT:最終的なコード、作業を再起動して:あなたは別のファイルにクラスタのコードを保存し、引数としてファイルへのパスで、このコードを起動する必要がありますでしょう

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:この例を最小限に抑えたエラーは、後でコードで使用しましたが、これを指摘してくれてありがとうございます。) – 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

+1動的な例では、自分のコードよりもきれいです。 – DrakaSAN

関連する問題