waffle
Version:
シンプルなWEBアプリケーションフレームワークです。(ALL YOUR NODE ARE BELONG TO US)
136 lines (117 loc) • 3.85 kB
JavaScript
/*
* Copyright 2012 Katsunori Koyanagi
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/**
* @overview アプリケーションのクラスタリング機能を提供するアドオンです。
* 処理の分散化及び、異常終了やタイムアウトした子プロセスの再起動をサポートします。
*/
;
var cluster = require("cluster");
var app = require("../Waffle");
function WorkerManager(options) {
var workers = {};
function checkChildProcesses() {
var now = process.uptime();
var timeout = options.timeout / 1000;
for ( var pid in workers) {
var worker = workers[pid];
if (now - worker.__heartbeat__ > timeout) {
app.log.error("worker %d timeouted.", worker.pid);
worker.kill();
}
}
setTimeout(checkChildProcesses, options.watch);
}
function createWorker() {
var worker = cluster.fork();
workers[worker.pid] = worker;
worker.__heartbeat__ = process.uptime();
worker.on("message", function(msg) {
if (msg === "heartbeat") {
worker.__heartbeat__ = process.uptime();
}
});
app.log("worker %d created.", worker.pid);
}
this.start = function() {
for ( var i = 0; i < options.forks; i++) {
createWorker();
}
cluster.on("death", function(worker) {
delete workers[worker.pid];
app.log.error("worker %d died.", worker.pid);
createWorker();
});
checkChildProcesses();
}
};
/**
* クラスタを開始します。
* <p>
* オプションは以下のように定義することができますが、省略することも可能です。
* </p>
* <table>
* <tr>
* <th>forks</th>
* <td>プロセスのフォーク数、省略時はOSが認識するCPU数が使用される</td>
* </tr>
* <tr>
* <th>timeout</th>
* <td>ワーカの実行がタイムアウトするまでのミリ秒の時間、省略時は3000ミリ秒</td>
* </tr>
* <tr>
* <th>heartbeat</th>
* <td>ワーカが生存中であることをマスタへ通知する間隔(ミリ秒)、省略時は1000ミリ秒</td>
* </tr>
* <tr>
* <th>watch</th>
* <td>ワーカが生存中であることをチェックする間隔(ミリ秒)、省略時は1000ミリ秒</td>
* </tr>
* </table>
*
* @example <code>
* var waffle = require("waffle");
* waffle.extensions.cluster(function(){
* waffle.start("foo/bar.json");
* });
* </code>
* @function
* @name Extensions#cluster
* @param {Function}
* callback ワーカとしてプロセスが起動した場合に呼ばれるコールバック関数
* @param {Object}
* options クラスタの管理に使用されるオプションのオブジェクト(省略可)
*
*/
module.exports = function(callback, options) {
options = options || {};
function setNumber(name, defaultValue) {
var num = parseInt(options[name], 10);
if (isNaN(num) || num < 1) {
num = defaultValue;
}
options[name] = num;
}
setNumber("forks", require("os").cpus().length);
setNumber("timeout", 3000);
setNumber("heartbeat", 1000);
setNumber("watch", 1000);
if (cluster.isMaster) {
new WorkerManager(options).start();
return;
}
setInterval(process.send, options.heartbeat, "heartbeat");
callback();
};