Created
September 9, 2012 10:18
-
-
Save yosuke-furukawa/3683651 to your computer and use it in GitHub Desktop.
コードの変更をキャッチして、GracefulなRestartをする方法
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var cluster = require('cluster'); | |
var http = require('http'); | |
var numCPUs = require('os').cpus().length / 2; | |
var numWorkers = numCPUs <= 1 ? 2 : numCPUs; | |
var watch = require('watch'); | |
var domain = require('domain'); | |
var util = require('util'); | |
var forceKilledWorkers = {}; | |
// cluster destroy if timeout. | |
var destroy = function() { | |
if (cluster.isWorker) { | |
var timeout = setTimeout(function() {cluster.worker.destroy();}, 120000); | |
forceKilledWorkers[cluster.worker.id] = timeout; | |
} | |
}; | |
var forkWorkers = function(num) { | |
var forkDomain = domain.create(); | |
forkDomain.on('error', function(error) { | |
util.log("error occured when starting new workers."); | |
util.log(error); | |
}); | |
forkDomain.run(function(){ | |
for (var i = 0; i < num; i++) { | |
cluster.fork(); | |
} | |
}); | |
}; | |
var disconnectCluster = function() { | |
var disconnectDomain = domain.create(); | |
disconnectDomain.on('error', function(error) { | |
util.log("error occured when disconnecting new workers."); | |
util.log(error); | |
destroy(); | |
}); | |
disconnectDomain.run(function() { | |
cluster.disconnect(); | |
}); | |
}; | |
var respawnWorkers = function(num) { | |
disconnectCluster(); | |
forkWorkers(num); | |
}; | |
watch.createMonitor(__dirname, function (monitor) { | |
monitor.on("created", function (f, stat) { | |
respawnWorkers(numWorkers); | |
}); | |
monitor.on("changed", function (f, curr, prev) { | |
respawnWorkers(numWorkers); | |
}); | |
monitor.on("removed", function (f, stat) { | |
respawnWorkers(numWorkers); | |
}); | |
}); | |
if (cluster.isMaster) { | |
forkWorkers(numWorkers); | |
cluster.on('disconnect', function(worker) { | |
util.log("worker("+worker.id+").disconnect " + worker.process.pid); | |
}); | |
cluster.on('exit', function(worker, code, signal) { | |
if (!worker.suicide) { | |
cluster.fork(); | |
} else { | |
util.log("worker("+worker.id+") is suicide."); | |
} | |
var timeout = forceKilledWorkers[worker.id]; | |
if (timeout) { | |
clearTimeout(timeout); | |
delete forceKilledWorkers[worker.id]; | |
} | |
util.log("worker("+worker.id+").exit " + worker.process.pid); | |
}); | |
cluster.on('fork', function(worker) { | |
util.log("worker("+worker.id+").fork"); | |
}); | |
cluster.on('online', function(worker) { | |
util.log("worker("+worker.id+").online " + worker.process.pid); | |
}); | |
cluster.on('listening', function(worker, address) { | |
util.log("worker("+worker.id+").listening " + address.address + ":" + address.port); | |
}); | |
} else if (cluster.isWorker) { | |
var server = http.createServer(function(req, res) { | |
res.writeHead(200, {'Content-Type': 'text/html'}); | |
res.end("<html><body><h1>Hello World.</h1></body></html>\n"); | |
}); | |
server.listen(3000); | |
server.on('close', function() { process.exit(); }); | |
} else { | |
util.log("unsupported cluster."); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Jxckさん、非常に非常に遅くなりましたが、修正してみました。
ベタ書きになっちゃいましたが、2分間、disconnectで失敗した後に強制終了させるようにしてみました。
同様にdomainでforkのエラーも検知するようにしてみました。
確かに。そうしましょう。でも万が一のworker、master以外の時はどうしようと思って、今は一応
ログに書くだけ、という対応になっています。
suicideもログに出してみました。
あと、suicideじゃないときはなんかの拍子に死んだ時なので、
その時はforkし直すようにしてみました。
var numCPUs = require('os').cpus().length / 2;
なんかで上のようにしているサンプルを見ました。
これだと半分しか使わない省エネ設定です。
他にも以下の様なのもみました。
var numCPUs = require('os').cpus().length - 2;
これだと必ず2個空けとくパターンですね。