Javascript Node.js:集群中代码不同的工作者?
我在node.js中有一个应用程序 本应用程序分为3个部分: launcher.js,它启动另外两个部分,并在处理清理后崩溃/更新时重新启动它们 app.js,可以自己在电脑上运行 用于访问日志和不同命令的server.js 启动器的简化代码为:Javascript Node.js:集群中代码不同的工作者?,javascript,node.js,Javascript,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.f
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时,我不得不重新启动服务器,有时不知道出了什么问题,这意味着要有一个我不喜欢的子shell
有没有一种方法可以分叉集群,但启动不同的代码
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);
}
}
var版本=0.3,
util=require('util'),
cluster=require('cluster'),
PATH=process.argv[1]。substr(0,process.argv[1]。lastIndexOf('/')+1),
lib=[],
childs=[];
函数监听(儿童,i){
子.on('message',函数(m){
如果(m.type==='REBOOT')
{
重新启动();
}else if(m.type=='CODE1'){
send({type:'START',c:lib[i]});
}否则{
日志('错误','');
}
});
子.on('exit',函数(工作者、代码、信号){
删除require.cache[require.resolve(PATH+lib[i]);
childs[i]=cluster.fork();
听(childs[i],i);
});
}
函数重新启动(){
i=0;
做
{
childs[i].kill();
i=i+1;
}而(i
您需要将群集代码存储在不同的文件中,并以文件路径作为参数启动此代码。我的解决方案:
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集群=需要(“集群”);
if(cluster.isMaster){
//基于args的Forking工人
如果(进程argv.length<3){
console.log(“用法:“+process.argv[1]+”模块[module]”);
}
process.argv.forEach(函数(val、索引、数组){
//不要将此脚本用作工作程序(索引1=self)
如果(索引>1){
//在生成之前解析模块以防止循环。
尝试{require.resolve(val);spawn(val);}
catch(e){console.error(“Module'+val+“'notfound”);}
}
});
集群打开(“退出”,功能(工作、代码、信号){
重生(工人);
});
}否则{
var self=require(process.env.WorkerScript);
self.start();
}
函数生成(脚本){
fork({WorkerScript:script}).env={WorkerScript:script};
}
功能再生(工人){
log(“重生:+worker.env.WorkerScript”)
cluster.fork(worker.env).env=worker.env;
}
在本例中,工人的数量是硬编码的。请看我的编辑,了解一个更动态的示例。为什么要包括require('child_process')。exec代码>在第一个代码示例中?我不知道你在哪里用这个anywhere@qodeninja:示例中出现错误,代码后面会用到它,但不是为了这个,谢谢您指出这一点:)