NodeJS|Cluster: Come inviare i dati da maestro a tutti o singolo bambino/lavoratori?

Ho lavoro (stock) di script da nodo

var cluster = require('cluster');
var http = require('http');
var numReqs = 0;

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

    worker.on('message', function(msg) {
      if (msg.cmd && msg.cmd == 'notifyRequest') {
        numReqs++;
      }
    });
  }

  setInterval(function() {
    console.log("numReqs =", numReqs);
  }, 1000);
} else {
  //Worker processes have a http server.
  http.Server(function(req, res) {
    res.writeHead(200);
    res.end("hello world\n");
    //Send message to master process
    process.send({ cmd: 'notifyRequest' });
  }).listen(8000);
}

Nello script precedente mi può inviare i dati dal lavoratore al processo master con facilità. Ma come inviare i dati dal master per il lavoratore/i lavoratori? Con esempi, se possibile.

InformationsquelleAutor htonus | 2011-12-16

 

5 Replies
  1. 39

    Perché cluster.la forcella è implementato su child_process.forcella, è possibile inviare messaggi da un master per il lavoratore utilizzando worker.send({ msg: 'test' }), e da un lavoratore per un master da process.send({ msg: 'test' });. Si ricevono i messaggi in questo modo: worker.on('message', callback) (dall’operaio al master) e process.on('message', callback); (da master a lavoratore).

    Ecco il mio esempio, è possibile testare la navigazione http://localhost:8000/ Quindi il lavoratore inviare un messaggio al master e il master risposta:

    var cluster = require('cluster');
    var http = require('http');
    var numReqs = 0;
    var worker;
    
    if (cluster.isMaster) {
      //Fork workers.
      for (var i = 0; i < 2; i++) {
        worker = cluster.fork();
    
        worker.on('message', function(msg) {
          //we only want to intercept messages that have a chat property
          if (msg.chat) {
            console.log('Worker to master: ', msg.chat);
            worker.send({ chat: 'Ok worker, Master got the message! Over and out!' });
          }
        });
    
      }
    } else {
      process.on('message', function(msg) {
        //we only want to intercept messages that have a chat property
        if (msg.chat) {
          console.log('Master to worker: ', msg.chat);
        }
      });
      //Worker processes have a http server.
      http.Server(function(req, res) {
        res.writeHead(200);
        res.end("hello world\n");
        //Send message to master process
        process.send({ chat: 'Hey master, I got a new request!' });
      }).listen(8000);
    }
    • In realtà voglio creare push server (web/flash)presa clienti. Versione corrente pile on 1000 connessioni simultanee. Così ho deciso di creare alcuni lavoratori con la presa di corrente.io ascoltatori. Questo significa che ho bisogno di passare i dati ai lavoratori in maniera asincrona.
    • Che suoni ok, accertarsi che la Presa di corrente.IO con RedisStore.
    • Questo non funziona. var all’interno for? worker terrà l’ultimo operaio a forcella, non tutti (specialmente all’interno dell’evento richiamata). O non si cura di tutti e non solo di allegare la callback o si tiene tutti i lavoratori in Array.
    • Mi dispiace per il var, ho copiato una parte del suo codice. Io non contenere tutti i miei operai in un array, perché ho solo voluto dimostrare la funzionalità.
    • Sarebbe l’invio dei dati attraverso il lavoratori di essere più lento o più veloce rispetto all’utilizzo di redis?
    • tbh non sono esattamente sicuro. Con il cluster si utilizza child_process che credo si apre un socket per gestire la comunicazione inter-processo. Si dovrebbe fare un paio di prove con i dati reali e vedere come se la cavano.
    • Se si desidera inviare gli oggetti JavaScript, è toJSON e fromJSON sull’altro lato?

  2. 8

    Ho trovato questo thread, mentre cerca di un modo per inviare un messaggio a tutti i processi figli e per fortuna era in grado di capire, grazie per i commenti sulle matrici. Volevo solo illustrare una possibile soluzione per l’invio di un messaggio a tutti i processi figli che utilizzano questo approccio.

    var cluster = require('cluster');
    var http = require('http');
    var numReqs = 0;
    var workers = [];
    
    if (cluster.isMaster) {
      //Broadcast a message to all workers
      var broadcast = function() {
        for (var i in workers) {
          var worker = workers[i];
          worker.send({ cmd: 'broadcast', numReqs: numReqs });
        }
      }
    
      //Fork workers.
      for (var i = 0; i < 2; i++) {
        var worker = cluster.fork();
    
        worker.on('message', function(msg) {
          if (msg.cmd) {
            switch (msg.cmd) {
              case 'notifyRequest':
                numReqs++;
              break;
              case 'broadcast':
                broadcast();
              break;
            }
        });
    
        //Add the worker to an array of known workers
        workers.push(worker);
      }
    
      setInterval(function() {
        console.log("numReqs =", numReqs);
      }, 1000);
    } else {
      //React to messages received from master
      process.on('message', function(msg) {
        switch(msg.cmd) {
          case 'broadcast':
            if (msg.numReqs) console.log('Number of requests: ' + msg.numReqs);
          break;
        }
      });
    
      //Worker processes have a http server.
      http.Server(function(req, res) {
        res.writeHead(200);
        res.end("hello world\n");
        //Send message to master process
        process.send({ cmd: 'notifyRequest' });
        process.send({ cmd: 'broadcast' });
      }).listen(8000);
    }
  3. 3

    Ecco come ho implementato una soluzione ad un problema simile. Agganciandosi cluster.on('fork'), è possibile allegare i gestori di messaggio per i lavoratori come sono a forcella (piuttosto che la loro memorizzazione in un array), che ha il vantaggio di trattare i casi in cui i lavoratori muoiono o si disconnette e un nuovo lavoratore è a forcella.

    Questo frammento potrebbe inviare un messaggio dal maestro tutti lavoratori.

    if (cluster.isMaster) {
        for (var i = 0; i < require('os').cpus.length; i++) {
            cluster.fork();
        }
    
        cluster.on('disconnect', function(worker) {
            cluster.fork();
        }
    
        //When a new worker process is forked, attach the handler
        //This handles cases where new worker processes are forked
        //on disconnect/exit, as above.
        cluster.on('fork', function(worker) {
            worker.on('message', messageRelay);
        }
    
        var messageRelay = function(msg) {
            Object.keys(cluster.workers).forEach(function(id) {
                cluster.workers[id].send(msg);
            });
        };
    }
    else {
        process.on('message', messageHandler);
    
        var messageHandler = function messageHandler(msg) {
            //Worker received message--do something
        };
    }
  4. 1

    Si dovrebbe essere in grado di inviare un messaggio dal maestro per il lavoratore come questo:

    worker.send({message:'hello'})

    perché “cluster.la forcella è implementato su child_process.forcella” (cluster.la forcella è implementato su child_process.forcella)

    • Sì funziona, grazie! In altre parole: mentre il fork di lavoratori dovrei memorizzare in un array. E ripetere questo array per inviare i dati per ogni bambino. C’è un altro modo per inviare i dati a tutti i lavoratori, senza la memorizzazione e l’iterazione.
    • Se non si desidera memorizzare i lavoratori in un array e lo scorrere attraverso di loro per l’invio di messaggi è possibile utilizzare un socket di dominio unix per comunicare messaggi dal maestro per i lavoratori.
    • Suppongo che si può creare un EventEmitter nel master, li emettono un evento ogni volta che viene ricevuto un messaggio. Dopo la creazione di ogni lavoratore, è solo bisogno di aggiungere un listener per il EventEmitter che invia il messaggio al lavoratore. Naturalmente questo è ancora implementata memorizzare i riferimenti degli ascoltatori (e quindi del lavoratore troppo) in EventEmitter, ma hey, almeno non devi guardare
  5. 1

    Capisco il vostro scopo di trasmissione per tutte il nodo processi di lavoro in un cluster, anche se non è possibile inviare presa component in quanto tale, ma c’è un lavoro in giro per lo scopo per essere servito. Vorrei provare a spiegare con un esempio :

    Passo 1 : Quando un client richiede una trasmissione :

    Child.js (Process that has been forked) :
    
    socket.on("BROADCAST_TO_ALL_WORKERS", function (data) 
    {
        process.send({cmd : 'BROADCAST_TO_ALL_WORKERS', message :data.message});
    }) 

    Passo 2 : creazione di cluster lato

    Server.js (Place where cluster forking happens):
    
    if (cluster.isMaster) {
    
      for (var i = 0; i < numCPUs; i++) {
    
        var worker = cluster.fork();
    
        worker.on('message', function (data) {
         if (data.cmd === "BROADCAST_TO_ALL_WORKERS") {
           console.log(server_debug_prefix() + "Server Broadcast To All, Message : " + data.message + " , Reload : " + data.reload + " Player Id : " + data.player_id);
            Object.keys(cluster.workers).forEach(function(id) {
                cluster.workers[id].send({cmd : "BROADCAST_TO_WORKER", message : data.message});
            });
          }
        });
      }
    
      cluster.on('exit', function (worker, code, signal) {
        var newWorker = cluster.fork();
        newWorker.on('message', function (data) {
          console.log(data);
          if (data.cmd === "BROADCAST_TO_ALL_WORKERS") {
            console.log(data.cmd,data);
            Object.keys(cluster.workers).forEach(function(id) {
                cluster.workers[id].send({cmd : "BROADCAST_TO_WORKER", message : data.message});
            });
          }
        });
      });
    } 
    else {
      //Node Js App Entry
      require("./Child.js");
    }

    Passo 3: Per Trasmettere il processo figlio –

    -> Mettere questo prima io.on(“connessione”) in Child.js

    process.on("message", function(data){
        if(data.cmd === "BROADCAST_TO_WORKER"){
            io.sockets.emit("SERVER_MESSAGE", { message: data.message, reload: data.reload, player_id : data.player_id });
        }
    });

    Spero che questo aiuta. Per favore fatemi sapere se ulteriori richieste di chiarimento.

Lascia un commento