СоХабр закрыт.
С 13.05.2019 изменения постов больше не отслеживаются, и новые посты не сохраняются.
cluster
. Так разработчику не приходится заботиться о конкурентности и писать свою систему балансировки, легко управлять количеством процессов и в случае падения одного из них, в целом приложение продолжает работать. Но решает ли это проблему отказоустойчивости? Не совсем! Потому что, если у вас в каждом из процессов есть сбойный модуль, он будет валить весь процесс вне зависимости работают ли исправно другие модули. Как известно способов отловить ошибку в nodejs почти нет: домены не в счет, а промисы еще только осваиваются разработчиками как инструмент.child_process.fork
, который, как и cluster.fork
является частным случаем child_process.spawn
, но с нюансами! Метод child_process.fork
позволяет создать процесс с указанным модулем и при этом создает канал для общения между процессами. Этот канал позволяет передавать JSON-объекты с помощью process.send
. Вот так:// ---- main.js ----
var fork = require('child_process').fork;
// Создаем дочерний процесс
var submodule = fork('./submodule.js');
// Добавляем обработчик событий для обмена сообщениями
submodule.on('message', function(msg) {
console.log('main', msg);
submodule.send(msg);
});
// ---- submodule.js ----
process.on('message', function(msg){
console.log('submodule', msg);
});
// Отправляем сообщение родительскому процессу
process.send('hi');
// ---- main.js ----
var fork = require('child_process').fork;
var submodule = fork('./submodule.js');
var stack = {};
var ts = Date.now();
var id = 0;
submodule.on('message', function(msg) {
if (msg.event !== 'result') return;
if (msg.id in stack == false) {
throw new Error('Message id not found');
}
var cb = stack[msg.id];
delete stack[msg.id];
cb.call(msg.args);
});
function sendCall(method, args, callback) {
// Обновляем счетчик с привязкой ко времени, чтобы избежать переполнения целочисленного id.
var ts1 = Date.now();
if (ts1 > ts) {
ts = ts1;
id = 0;
}
// Генерируем сам id
++id;
var messageId = ts + '.' + id;
// Отправляем запрос
submodule.send({
id : messageId,
event : 'method',
method : method,
args : args
});
}
// ---- submodule.js ----
var api = {
hello : function(name, callback) {
callback(null, 'Hello, ' + name + '!');
}
};
process.on('message', function(msg){
if (msg.event !== 'method') retrun;
if (event.method in api === false) {
process.send({
id : msg.id,
args : [new Error('Method not found')]
});
} else {
// Вызваем метод с колбеком
var cb = function(){
process.send({
id : msg.id,
event : 'result',
args : arguments
});
};
try {
api[msg.method].apply(api, msg.args.concat(cb));
} catch (err) {
cb(err);
}
}
});
submodule.hello('%username%', function(err, msg) {
console.log(msg) //-> Hello, %username%!
})
uncaughtException
дочернего модуля. Это поможет вам лучше понимать из-за чего приложение перестало работать.process.send
не желательно для больших данных, так как является блокирующим. В замен рекомендуется передать tcp-соединение в дочерний процесс вторым аргументом через тот же метод process.send
. Так можно будет отправлять большие сообщения и файлы.
комментарии (2)