У нас мало процессов node.js, которые должны иметь возможность передавать сообщения, Какой самый эффективный способ сделать это? Как насчет использования node_redis pub/sub
EDIT: процессы могут выполняться на разных машинах
У нас мало процессов node.js, которые должны иметь возможность передавать сообщения, Какой самый эффективный способ сделать это? Как насчет использования node_redis pub/sub
EDIT: процессы могут выполняться на разных машинах
Если вы хотите отправлять сообщения с одной машины на другую и не заботиться о обратных вызовах, то 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, если вам нужно "отправить и забыть" сообщение, исследуйте другие решения, если вам нужна полноценная двунаправленная связь.
Почему бы не использовать ZeroMQ/0mq для IPC? Redis (база данных) слишком много убивает, делая что-то столь же простое, как IPC.
Цитирование руководства:
ØMQ (ZeroMQ, 0MQ, zmq) выглядит как встраиваемая сетевая библиотека но действует как структура concurrency. Это дает вам гнезда, которые несут атомных сообщений в различных транспортных средствах, таких как in-process, межпроцессный, 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):
Спустя более 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);
}
);
}
);
Im в настоящее время оценивает этот модуль для замены локального ipc (но может быть удаленным ipc в будущем) в качестве замены старого решения через stdin/stdout. Может быть, я расширю свой ответ, когда закончим, чтобы дать дополнительную информацию о том, как и как хорошо работает этот модуль.
i начнется со встроенных функций, предоставляемых node.
вы можете использовать сигнализацию процесса, например:
process.on('SIGINT', function () {
console.log('Got SIGINT. Press Control-D to exit.');
});
эта сигнализация
Излучается, когда процессы получают сигнал. См. Sigaction (2) для список стандартных имен сигналов POSIX, таких как SIGINT, SIGUSR1 и т.д.
Как только вы узнаете о процессе, вы можете создать дочерний процесс и подключить его к событию message
для извлечения и отправки сообщений. При использовании child_process.fork()
вы можете записать дочерний элемент с помощью child.send(message, [sendHandle])
, и сообщения будут получены событием "сообщение" для дочернего элемента.
Кроме того, вы можете использовать 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, signals и bean.
взгляните на node -messenger
https://github.com/weixiyen/messenger.js
будет соответствовать большинству потребностей легко (паб/под... огонь и забыть.. отправить/запросить) с автоматическим поддерживаемым соединением
мы работаем над многопроцессорным приложением node, которое требуется для обработки большого количества сообщений перекрестного процесса в реальном времени.
Сначала мы попробовали redis-pub-sub, который не соответствовал требованиям.
Затем попробовал tcp socket, который был лучше, но все же не самый лучший.
Итак, мы перешли на UDP-дейтаграмму, что намного быстрее.
Вот код репо, всего несколько строк кода. https://github.com/SGF-Games/node-udpcomm