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


Nous avons peu de processus node.js qui devraient pouvoir transmettre des messages, Quel est le moyen le plus efficace de le faire? Que diriez-vous d'utiliser node_redis pub / sub

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


46
2018-06-24 05:51


origine


Réponses:


Si vous voulez 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 très facile à mettre en œuvre et Redis est vraiment rapide.

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

Il est vraiment 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 sauter your_namespace et utiliser un espace de noms global, mais vous le regretterez tôt ou tard.

Il est très facile d’envoyer des messages aussi:

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 pmessages 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 ex. 'send_email'). Dans ce cas, le processus (ou la machine) peut être abonné à plusieurs canaux s'il implémente plusieurs fonctionnalités.

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

Donc, ma conclusion est la suivante: Utilisez Redis si vous avez besoin d'une communication «envoyer et oublier», étudiez d'autres solutions si vous avez besoin d'une communication bidirectionnelle complète.


36
2017-09-16 15:51



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

Citant le guide:

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

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 convient le mieux au scénario que vous décrivez. Si vous envoyez simplement des messages à différents 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 propose également différents types de socket (PUSH / PULL / XREP / XREQ / ROUTER / DEALER) avec lesquels vous pouvez créer des périphériques 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. Cela prend en charge le filtrage côté PUBLISHER pour PUBSUB):

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


31
2017-09-17 17:16



Plus de 4 ans après la question posée, il existe un module de communication interprocessus appelé noeud-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 sockets Unix, sockets Windows et sockets 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();

Client pour sockets Unix et sockets 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);
            }
        );
    }
);

J'évalue actuellement ce module pour un remplacement local ipc (mais pourrait être à distance ipc à l'avenir) en remplacement d'une ancienne solution via stdin / stdout. Je vais peut-être élargir ma réponse lorsque j'aurai fini de donner plus d'informations sur le fonctionnement de ce module.


26
2017-11-26 21:45



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

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

cette signalisation

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

Une fois que vous connaissez le processus, vous pouvez créer un processus enfant et le raccorder à la message événement pour retriver et envoyer des messages. En utilisant child_process.fork() vous pouvez écrire à l'enfant en utilisant child.send(message, [sendHandle]) et les messages sont reçus par un événement de message sur l'enfant.

Aussi - vous pouvez utiliser grappe. Le module de cluster vous permet de créer facilement un réseau de processus partageant tous des ports de 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, des signaux et haricot.


5
2017-09-12 12:11



jetez un oeil à node-messenger

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

s'adaptera facilement à la plupart des besoins (pub / sub ... feu et oublie .. envoyer / demander) avec pool de connexion automatique maintenu


2
2018-05-27 11:48



Nous travaillons sur une application de noeud multi-processus, nécessaire pour gérer un grand nombre de messages inter-processus en temps réel.

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

Puis essayé TCP socket, 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 repo du code, juste quelques lignes de code. https://github.com/SGF-Games/node-udpcomm


1
2017-09-29 07:46