6

Server NodeJS con un Mongo DB: una funzione genererà un file JSON di report dal DB, che può richiedere un po 'di tempo (60 secondi in su - deve elaborare centinaia di migliaia di voci).Come eseguire/interrompere attività a lungo termine in Node JS?

Vogliamo eseguire questo come attività in background. Dobbiamo essere in grado di avviare un processo di creazione di report, monitorarlo e interromperlo se l'utente decide di modificare i param e ricostruirlo.

Qual è l'approccio più semplice con il nodo? Non voglio davvero entrare nei regni di server worker separati che elaborano lavori, code di messaggi, ecc. - dobbiamo mantenere questo nella stessa scatola e un'implementazione abbastanza semplice.

1) Avviare la build come metodo asincrono e tornare all'utente, con lo stato di reporting socket.io?

2) Spin off un processo figlio per lo script di compilazione?

3) Utilizzare qualcosa come https://www.npmjs.com/package/webworker-threads?

Con i pochi approcci che ho guardato rimango bloccato nelle stesse due aree;

1) Come monitorare i progressi? 2) Come interrompere un processo di compilazione esistente se l'utente invia nuovamente i dati?

Qualsiasi puntatori sarebbe molto apprezzato ...

risposta

5

La cosa migliore sarebbe quella di separare questo compito dall'applicazione principale. Detto questo, sarebbe facile eseguirlo in background. Per eseguirlo in background e monitorare senza coda di messaggi ecc., Il più semplice sarebbe uno child_process.

  1. È possibile avviare un lavoro spawn su un endpoint (o url) chiamato dall'utente.
  2. Successivamente, configurare un socket per restituire il monitoraggio dal vivo del processo di
  3. bambino Aggiungi un altro endpoint per fermare il lavoro, con un ID univoco restituito da 1. (o meno, a seconda delle vostre esigenze di concorrenza)

alcune idee di codifica:

var spawn = require('child_process').spawn 

var job = null //keeping the job in memory to kill it 

app.get('/save', function(req, res) { 

    if(job && job.pid) 
     return res.status(500).send('Job is already running').end() 

    job = spawn('node', ['/path/to/save/job.js'], 
    { 
     detached: false, //if not detached and your main process dies, the child will be killed too 
     stdio: [process.stdin, process.stdout, process.stderr] //those can be file streams for logs or wathever 
    }) 

    job.on('close', function(code) { 
     job = null 
     //send socket informations about the job ending 
    }) 

    return res.status(201) //created 
}) 

app.get('/stop', function(req, res) { 
    if(!job || !job.pid) 
     return res.status(404).end() 

    job.kill('SIGTERM') 
    //or process.kill(job.pid, 'SIGTERM') 
    job = null 
    return res.status(200).end() 
}) 

app.get('/isAlive', function(req, res) { 
    try { 
     job.kill(0) 
     return res.status(200).end() 
    } catch(e) { return res.status(500).send(e).end() } 
}) 

per Monit il processo figlio si potrebbe usare pidusage, lo usiamo in PM2 per esempio. Aggiungi un percorso per monitorare un lavoro e chiamarlo ogni secondo. Non dimenticare di rilasciare memoria quando il lavoro termina.


Si potrebbe voler controllare this library che vi aiuterà a gestire più di elaborazione tra microservices.

+0

Grazie per la risposta @soyuka. Con il 'job' var - che mantiene il riferimento al bambino, così puoi fermarlo - ma funziona su PID? I PID vengono riutilizzati, vero? Quindi il lavoro che creiamo potrebbe essere completato e il PID viene liberato per qualsiasi altro nuovo processo da intraprendere? Ciò significa che job.kill() potrebbe potenzialmente uccidere un processo diverso se funziona con il solo PID? Oppure non funziona così ... –

+0

Basta controllare i documenti e dice ... "Può emettere un evento 'errore' quando il segnale non può essere consegnato.L'invio di un segnale a un processo figlio che è già uscito non è un errore ma può avere conseguenze impreviste: se il PID (l'ID del processo) è stato riassegnato a un altro processo, il segnale verrà consegnato a quel processo. Quello che succede dopo è l'ipotesi di chiunque. "Ma azzerare il riferimento al completamento dovrebbe risolverlo come per il tuo exmaple !! Mi dispiace, mi sono perso. –

+0

Questo codice sembra consentire solo un processo di reporting alla volta e sovrascriverà (e perderà la traccia del lavoro precedente) se viene effettuato un tentativo di avviare un secondo 1. – jfriend00

Problemi correlati