Какая библиотека / метод межпроцессного взаимодействия является наиболее эффективной в node.js? - PullRequest
54 голосов
/ 24 июня 2011

У нас есть несколько процессов node.js, которые должны иметь возможность передавать сообщения, Какой самый эффективный способ сделать это? Как насчет использования node_redis pub / sub

РЕДАКТИРОВАТЬ: процессы могут выполняться на разных машинах

Ответы [ 6 ]

41 голосов
/ 16 сентября 2012

Если вы хотите отправлять сообщения с одного компьютера на другой и не беспокоиться о обратных вызовах, тогда Redis pub / sub - лучшее решение.Его очень легко реализовать, а Redis действительно быстр.

Сначала вам нужно установить Redis на одну из ваших машин.

Его действительно легко подключить к Redis:

var client = require('redis').createClient(redis_port, redis_host);

Но не забывайте об открытии порта Redis в брандмауэре!

Затем вам нужно подписать каждую машину на какой-то канал:

client.on('ready', function() {
  return client.subscribe('your_namespace:machine_name');
});

client.on('message', function(channel, json_message) {
  var message;
  message = JSON.parse(message);
  // do whatever you vant with the message
});

Вы можете пропустить your_namespace и использовать глобальное пространство имен, но вы будете сожалеть об этом рано или поздно.

Также очень легко отправлять сообщения:

var send_message = function(machine_name, message) {
  return client.publish("your_namespace:" + machine_name, JSON.stringify(message));
};

Если вы хотите отправлять различные виды сообщений, вы можете использовать pmessages вместосообщения:

client.on('ready', function() {
  return client.psubscribe('your_namespace:machine_name:*');
});

client.on('pmessage', function(pattern, channel, json_message) {
  // pattern === 'your_namespace:machine_name:*'
  // channel === 'your_namespace:machine_name:'+message_type
  var message = JSON.parse(message);
  var message_type = channel.split(':')[2];
  // do whatever you want with the message and message_type
});

send_message = function(machine_name, message_type, message) {
  return client.publish([
    'your_namespace',
    machine_name,
    message_type
  ].join(':'), JSON.stringify(message));
};

Рекомендуется называть ваши процессы (или машины) по их функциональности (например, 'send_email').В этом случае процесс (или машина) может быть подписан более чем на один канал, если он реализует более одной функциональности.

На самом деле, возможно создать двунаправленную связь с использованием Redis.Но это более сложно, так как для каждого обратного вызова необходимо добавить уникальное имя канала обратного вызова для получения обратного вызова без потери контекста.

Итак, мой вывод такой: Используйте Redis, если вам нужно "отправить изабудьте "общение", найдите другие решения, если вам нужна полноценная двусторонняя связь .

32 голосов
/ 17 сентября 2012

Почему бы не использовать ZeroMQ / 0mq для IPC?Redis (база данных) слишком сложна для выполнения таких простых действий, как IPC.

Цитирование руководства:

ØMQ (ZeroMQ, 0MQ, zmq) выглядит как встраиваемая сетевая библиотекано действует как структура параллелизма.Это дает вам сокеты, которые переносят атомарные сообщения через различные транспорты, такие как внутрипроцессный, межпроцессный, TCP и многоадресная передача.Вы можете соединить сокеты N-to-N с такими шаблонами, как разветвление, pub-sub, распределение задач и запрос-ответ.Это достаточно быстро, чтобы быть тканью для кластерных продуктов.Его модель асинхронного ввода-вывода предоставляет масштабируемые многоядерные приложения, созданные как задачи асинхронной обработки сообщений.

Преимущество использования 0MQ (или даже ванильных сокетов через сетевую библиотеку в ядре Node, за вычетом всех функцийобеспечивается сокетом 0MQ), что нет главного процесса.Его настройка без посредников лучше всего подходит для сценария, который вы описываете.Если вы просто отправляете сообщения на различные узлы из одного центрального процесса, вы можете использовать сокет PUB / SUB в 0mq (также поддерживает многоадресную IP-рассылку через PGM / EPGM).Кроме того, 0mq также предоставляет различные типы сокетов (PUSH / PULL / XREP / XREQ / ROUTER / DEALER), с помощью которых вы можете создавать собственные устройства.

Начните с этого превосходного руководства: http://zguide.zeromq.org/page:all

Для 0MQ 2.x:

http://github.com/JustinTulloss/zeromq.node

Для 0MQ 3.x (вилка вышеупомянутого модуля. Поддерживает фильтрацию на стороне PUBLISHER для PUBSUB):

http://github.com/shripadk/zeromq.node

31 голосов
/ 27 ноября 2015

Более чем через 4 года после задаваемого вопроса существует модуль межпроцессного взаимодействия под названием node-ipc . Он поддерживает сокеты Unix / Windows для связи на том же компьютере, а также TCP, TLS и UDP, утверждая, что по крайней мере сокеты, TCP и UDP стабильны.

Вот небольшой пример, взятый из документации из репозитория github:

Сервер для Unix-сокетов, Windows-сокетов и TCP-сокетов

var ipc=require('node-ipc');

ipc.config.id   = 'world';
ipc.config.retry= 1500;

ipc.serve(
    function(){
        ipc.server.on(
            'message',
            function(data,socket){
                ipc.log('got a message : '.debug, data);
                ipc.server.emit(
                    socket,
                    'message',
                    data+' world!'
                );
            }
        );
    }
);

ipc.server.start();

Клиент для Unix-сокетов и TCP-сокетов

var ipc=require('node-ipc');

ipc.config.id   = 'hello';
ipc.config.retry= 1500;

ipc.connectTo(
    'world',
    function(){
        ipc.of.world.on(
            'connect',
            function(){
                ipc.log('## connected to world ##'.rainbow, ipc.config.delay);
                ipc.of.world.emit(
                    'message',
                    'hello'
                )
            }
        );
        ipc.of.world.on(
            'disconnect',
            function(){
                ipc.log('disconnected from world'.notice);
            }
        );
        ipc.of.world.on(
            'message',
            function(data){
                ipc.log('got a message from world : '.debug, data);
            }
        );
    }
);

В настоящее время я оцениваю этот модуль на предмет замены локального ipc (но в будущем он может быть удаленным ipc) в качестве замены старого решения через stdin / stdout. Возможно, я расширю свой ответ, когда закончу, чтобы дать больше информации о том, как и насколько хорошо работает этот модуль.

8 голосов
/ 12 сентября 2012

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

process.on('SIGINT', function () {
  console.log('Got SIGINT.  Press Control-D to exit.');
});

эта сигнализация

Издается, когда процессы получают сигнал.См. Sigaction (2) для списка стандартных имен сигналов POSIX, таких как SIGINT, SIGUSR1 и т. Д.

Как только вы узнаете о процессе, вы можете запустить child-process и перехватитьвплоть до события message для извлечения и отправки сообщений.При использовании child_process.fork() вы можете писать дочернему элементу, используя child.send(message, [sendHandle]), и сообщения получаются с помощью события message в дочернем элементе.

Также - вы можете использовать cluster .Модуль кластера позволяет легко создавать сеть процессов, которые совместно используют порты сервера.

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', function(worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died');
  });
} else {
  // Workers can share any TCP connection
  // In this case its a HTTP server
  http.createServer(function(req, res) {
    res.writeHead(200);
    res.end("hello world\n");
  }).listen(8000);
}

Для сторонних сервисов вы можете проверить: hook.io , сигналов и боб .

2 голосов
/ 27 мая 2013

взгляните на узел-мессенджер

https://github.com/weixiyen/messenger.js

легко удовлетворит большинство потребностей (паб / саб ... запустить и забыть .. отправить / запрос) с автоматически поддерживаемым пулом соединений

1 голос
/ 29 сентября 2012

мы работаем над многопроцессорным узлом приложения, которое требуется для обработки большого количества межпроцессных сообщений в режиме реального времени.

Сначала мы попробовали redis-pub-sub, который не соответствовал требованиям.

Затем попробовал tcp socket, который был лучше, но все же не самый лучший.

Итак, мы переключились на дейтаграмму UDP, это намного быстрее.

Вот репозиторий, всего несколько строк кода. https://github.com/SGF-Games/node-udpcomm

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...