web-dev-qa-db-fra.com

Quelle est la bibliothèque / méthode de communication inter-processus node.js la plus efficace?

Nous avons peu de processus node.js qui devraient être capables de transmettre des messages. Quelle est la manière la plus efficace de le faire? Que diriez-vous d'utiliser node_redis pub/sub

EDIT: les processus peuvent s'exécuter sur différentes machines

54
DuduAlul

Si vous souhaitez envoyer des messages d'une machine à une autre et que vous ne vous souciez pas des rappels, Redis pub/sub est la meilleure solution. C'est vraiment facile à mettre en œuvre et Redis est vraiment rapide.

Vous devez d'abord installer Redis sur l'une de vos machines.

Il est très facile de se connecter à Redis:

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

Mais n'oubliez pas d'ouvrir le port Redis dans votre pare-feu!

Ensuite, vous devez abonner chaque machine à une chaîne:

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
});

Vous pouvez ignorer your_namespace et utiliser l'espace de noms global, mais vous le regretterez tôt ou tard.

Il est également très facile d'envoyer des messages:

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

Si vous souhaitez envoyer différents types de messages, vous pouvez utiliser des messages pm au lieu de messages:

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));
};

La meilleure pratique consiste à nommer vos processus (ou machines) par leur fonctionnalité (par exemple 'send_email'). Dans ce cas, le processus (ou la machine) peut être abonné à plusieurs canaux s'il met en œuvre plusieurs fonctionnalités.

En fait, il est possible de construire une communication bidirectionnelle en utilisant redis. Mais c'est plus délicat car il faudrait ajouter un nom de canal de rappel unique à chaque message afin de recevoir le rappel sans perdre le contexte.

Donc, ma conclusion est la suivante: tilisez Redis si vous avez besoin d'une communication "envoyer et oublier", cherchez d'autres solutions si vous avez besoin d'une communication bidirectionnelle à part entière.

42
Leonid Beschastny

Pourquoi ne pas utiliser ZeroMQ/0mq pour IPC? Redis (une base de données) est exagéré pour avoir fait quelque chose d'aussi simple que IPC.

Citant le guide:

ØMQ (ZeroMQ, 0MQ, zmq) ressemble à une bibliothèque de mise en réseau intégrable mais agit comme un framework de concurrence. Il vous donne des sockets qui transportent des messages atomiques à travers différents transports comme in-process, inter-process, TCP et multicast. Vous pouvez connecter des sockets N à N avec des modèles tels que fanout, pub-sub, distribution de tâches et request-reply. Il est assez rapide pour être le tissu des produits en cluster. Son modèle d'E/S asynchrone vous offre des applications multicœurs évolutives, conçues comme des tâches de traitement des messages asynchrones.

L'avantage d'utiliser 0MQ (ou même des sockets Vanilla via la bibliothèque net dans Node core, moins toutes les fonctionnalités fournies par un socket 0MQ) est qu'il n'y a pas de processus maître. Sa configuration sans courtier est le mieux adapté au scénario que vous décrivez. Si vous envoyez simplement des messages à divers nœuds à partir d'un processus central, vous pouvez utiliser le socket PUB/SUB dans 0mq (prend également en charge la multidiffusion IP via PGM/EPGM). En dehors de cela, 0mq prévoit également différents types de socket (Push/PULL/XREP/XREQ/ROUTER/DEALER) avec lesquels vous pouvez créer des appareils personnalisés.

Commencez avec cet excellent guide: http://zguide.zeromq.org/page:all

Pour 0MQ 2.x:

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

Pour 0MQ 3.x (Un fork du module ci-dessus. Il prend en charge le filtrage latéral PUBLISHER pour PUBSUB):

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

33
Shripad Krishna

Plus de 4 ans après la question posée, il existe un module de communication interprocessus appelé node-ipc . Il prend en charge les sockets unix/windows pour la communication sur la même machine ainsi que TCP, TLS et UDP, affirmant qu'au moins les sockets, TCP et UDP sont stables.

Voici un petit exemple tiré de la documentation du dépôt github:

Serveur pour les sockets Unix, les sockets Windows et TCP Sockets

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();

Client pour les sockets Unix et TCP Sockets

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 évalue actuellement ce module pour un ipc local de remplacement (mais pourrait être un ipc distant à l'avenir) en remplacement d'une ancienne solution via stdin/stdout. Peut-être que j'élargirai ma réponse lorsque j'aurai terminé pour donner plus d'informations sur le fonctionnement et la qualité de ce module.

31
morten.c

je commencerais par la fonctionnalité intégrée fournie par le nœud.
vous pouvez utiliser signalisation de processus comme:

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

cette signalisation

Émis lorsque le processus reçoit un signal. Voir sigaction (2) pour une liste des noms de signaux POSIX standard tels que SIGINT, SIGUSR1, etc.

Une fois que vous connaissez le processus, vous pouvez générer un child-process et le connecter à l'événement message pour récupérer et envoyer des messages. Lorsque vous utilisez child_process.fork(), vous pouvez écrire à l'enfant à l'aide de child.send(message, [sendHandle]) et les messages sont reçus par un événement "message" sur l'enfant.

Aussi - vous pouvez utiliser cluster . Le module de cluster vous permet de créer facilement un réseau de processus qui partagent tous les ports du serveur.

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);
}

Pour les services tiers, vous pouvez vérifier: hook.io , signaux et bean .

8
Sagiv Ofek

jetez un œil à node-messenger

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

s'adaptera à la plupart des besoins facilement (pub/sous-marin ... feu et oubliez .. envoyer/demander) avec connexion automatique maintenue

2
Niels

nous travaillons sur une application de nœud multi-processus, qui est nécessaire pour gérer un grand nombre de messages inter-processus en temps réel.

Nous avons d'abord essayé redis-pub-sub, qui n'a pas répondu aux exigences.

Ensuite, j'ai essayé le socket TCP, ce qui était mieux, mais toujours pas le meilleur.

Nous sommes donc passés au datagramme UDP, ce qui est beaucoup plus rapide.

Voici le dépôt de code, juste quelques lignes de code. https://github.com/SGF-Games/node-udpcomm

1
teleme.io