NodeJS Cluster-hub. Обмен сообщениями в cluster, запросы, межпроцессные эксклюзивные блокировки (критические секции)

в 13:56, , рубрики: cluster, javascript, node.js, метки: ,

Работая в очередной раз с модулем cluster, у меня возникла необходимость обмена сообщениями между рабочими процессами. К сожалению стандартный функционал модуля позволяет отправлять сообщения только с master процесса на worker, и в обратном направлении. При этом нет возможности получить какой-то ответ на сообщение, а очень хотелось бы. Поэтому я написал модуль cluster-hub. Возможно кому-нибудь он пригодится.

Модуль позволяет

  • Отправлять сообщения master->worker, worker->master, master->master
  • Отправлять запросы и получать ответы (через callback)
  • Использовать эксклюзивные блокировки по ключу (критические секции)

Кому интересно — прошу под кат.

Обмен сообщениями

Самый простой функционал — просто отправка сообщений в другие процессы. Есть возможность отправлять сообщения из master в worker, из worker в master, из master->master.

var Hub = require('cluster-hub');
var cluster = require('cluster');

var hub = new Hub(cluster);
if (cluster.isMaster) {
    var worker = cluster.fork();

    hub.on('master-to-master', function (data) {
        console.log('master-to-master received');
    });
    hub.on('worker-to-master', function (data) {
        console.log('worker-to-master received');
    });

    hub.sendToMaster('master-to-master', 1);
    hub.sendToWorker(worker, 'master-to-worker');
} else {
    hub.on('master-to-worker', function () {
        console.log('master-to-worker received');;
        process.exit();
    });

    hub.sendToMaster('worker-to-master', 2);
}

Отправка запросов

Данный функционал позволяет отправить запрос из одного процесса в другой и получить результат внутри callback функции. Пример сам за себя все скажет:

var Hub  = require('cluster-hub');
var cluster = require('cluster');
var hub = new Hub(cluster);

if (cluster.isMaster) {
    // in master process
    hub.on('sum', function (data, sender, callback) {
        callback(null, data.a + data.b);
    });

    var worker = cluster.fork();
} else {
    //in worker process
    hub.requestMaster('sum', {a: 1, b:2}, function (err, sum) {
        console.log('Sum in worker: ' + sum);
        process.exit();
    });
}

По аналогии можно использовать метод requestWorker, чтобы с master процесса вызвать метод на worker процессе.

Эксклюзивные блокировки / Критические секции

Данный функционал позволяет получить эксклюзивный доступ к какому-либо ресурсу одному из процессов (неважно — master или один из worker). Если worker процесс прекращает свою работу, не вызвав unlock для заблокированного ресурса — ресурс освободится автоматически.

var Hub = require('cluster-hub');
var cluster = require('cluster');

var hub = new Hub(cluster);

if (cluster.isMaster) {
    var worker = cluster.fork();

    hub.lock('foo', function (unlock) {
        console.log('foo lock in master');
        setTimeout(unlock, 1000);
    });


} else {
    hub.lock('foo', function (unlock) {
        console.log('foo lock in worker 1');
        setTimeout(unlock, 500);
    });

    hub.lock('bar', function (unlock) {
        console.log('bar lock in worker');
        unlock();
    })

    hub.lock('foo', function (unlock) {
        console.log('second foo lock in worker');
        unlock();
        process.exit();
    })
}

исходные коды модуля доступны тут: github.com/sirian/node-cluster-hub

Автор: Sirian

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js