Utilizzando il modulo cluster Node con SailsJs: EADDRINUSE

Ho un’applicazione basata su SailsJs ( http://sailsjs.org/ ) che ha a che fare con alcune attività intensive della CPU. In breve, voglio utilizzare il modulo cluster ( https://nodejs.org/api/cluster.html ) per debind l’elaborazione di queste attività ai processi di lavoro in modo che il ciclo di eventi principale dell’applicazione Sails non sia bloccato ( e così può rispondere alle richieste normalmente).

Durante la creazione di un lavoratore, sto ricevendo un errore EADDRINUSE mentre Sails sta tentando di eseguire nuovamente e associare alla stessa porta.

Codice di esempio:

 // SomeSailsService.js var cluster = require('cluster'); var Queue = require('bull'); var myQueue = Queue('myQueue', 'connection stuff', 'etc'); var numWorkers = 2; var i; if (cluster.isMaster) { // Spawn some workers for (i = 0; i < numWorkers; i++) { cluster.fork(); } } else { // This is a worker, so bind to new job event myQueue.process(function processJob(job, done) { // CPU intensive shenanigans }); } module.exports = { addToQueue: function(foo) { myQueue.add({foo: foo}); } }; 

Quando si esegue quanto sopra, viene avviata l’app Sails, quindi all’avvio i due worker tentano di avviare l’app altre due volte. Ciò si traduce in due dei seguenti errori:

 events.js:72 throw er; // Unhandled 'error' event ^ Error: bind EADDRINUSE at errnoException (net.js:904:11) at net.js:1084:30 at Object.1:1 (cluster.js:594:5) at handleResponse (cluster.js:171:41) at respond (cluster.js:192:5) at handleMessage (cluster.js:202:5) at process.emit (events.js:117:20) at handleMessage (child_process.js:322:10) at child_process.js:396:7 at process.handleConversion.net.Native.got (child_process.js:91:7) at process. (child_process.js:395:13) at process.emit (events.js:117:20) at handleMessage (child_process.js:322:10) at Pipe.channel.onread (child_process.js:347:11) 

C’è un modo per aggirare questo? O un modo alternativo di affrontare questo problema?

Ho finito per seguire il consiglio di questo post sul blog per avviare le istanze barebone dell’applicazione. A seguito di ciò, il processo di base per risolvere il mio problema è stato:

  • In app.js , controlla se cluster.isMaster === true .
  • In tal caso, avviare l’app normalmente e creare processi di lavoro.
  • In caso contrario, si tratta di un processo di lavoro, quindi avvia una versione minima dell’app senza il server HTTP . Registrare i gestori del processo di lavoro.

Il post del blog di cui sopra va più nel dettaglio (inclusa un’implementazione piuttosto piacevole) su come gestire la creazione e la registrazione di questi gestori di processi. Non menziona la gestione del cluster , ma si spera che i passaggi precedenti aiutino chiunque abbia incontrato questo problema.

MODIFICARE:

Su consiglio di Travis (vedi sotto commento), ho abbandonato l’uso del modulo cluster e invece worker.js creato un file worker.js che ha fatto la stessa cosa. Ad esempio, in worker.js ho avviato un’app Sails barebone che ha iniziato ad ascoltare nuovi lavori. La mia app principale Sails (l’API Web) è quindi solo retriggers per l’aggiunta e l’ottenimento di lavori (materiale a bassa latenza).

Funziona bene e dovrebbe funzionare facilmente con servizi come Heroku.