2013-08-03 2 views
6

C'è codice,parallelo asincrono Node.js - quali sono le conseguenze?

async.series(tasks, function (err) { 
    return callback ({message: 'tasks execution error', error: err}); 
}); 

dove, tasks è gamma di funzioni, ciascuna di essa peforms richiesta HTTP (utilizzando il modulo request) e chiamando MongoDB API per memorizzare i dati (per esempio MongoHQ).

Con il mio ingresso di corrente, (~ 200 compito da eseguire), ci vuole

[normal mode] collection cycle: 1356.843 sec. (22.61405 mins.) 

Ma semplicemente cercando cambiamento series-parallel, dà magnifico beneficio. La quasi identica quantità di attività viene eseguita in ~30 secs anziché in ~23 mins.

Ma, sapendo che nulla è gratis, sto cercando di capire quali sono le conseguenze di questo cambiamento? Posso dire che il numero di socket aperti sarà molto più alto, più consumo di memoria, più successo ai server DB?

La macchina su cui eseguo il codice è solo 1 GB di RAM Ubuntu, quindi l'app si blocca una volta sola, può essere causata dalla mancanza di risorse?

+1

Probabilmente dovresti modificare e usare 'async.parallelLimit (array, limit, cb)' per prestazioni migliori. Trova un limite di esecuzioni parallele che non eccedano l'esecuzione, e sarà più veloce di async.parallel: P Come bonus, non si bloccherà più :) – randunel

risposta

5

Il tuo intuito è corretto sul fatto che il parallelismo non viene fornito gratuitamente, ma sicuramente potresti riuscire a pagarlo.

Utilizzando un modulo di test di carico (o una raccolta di moduli) come nodeload, è possibile quantificare come questa operazione parallela influisce sul server per determinare se è accettabile.

Async.parallelLimit può essere un buon modo di limitare il carico del server se è necessario, ma prima è importante scoprire se la limitazione è necessaria. Il test esplicito è il modo migliore per scoprire i limiti del tuo sistema (ogniLimit ha una firma diversa, ma potrebbe essere usato anche).

Oltre a ciò, le insidie ​​più comuni che utilizzano async.parallel includono il volere un flusso di controllo più complicato di quello che offre la funzione (che, dalla tua descrizione non sembra applicabile) e l'uso parallelo di una raccolta troppo ingenua (che, per esempio , potrebbe farti imbattersi nel limite del descrittore di file del tuo sistema se stai scrivendo molti file). Con le tue ~ 200 operazioni di richiesta e salvataggio su 1GB di RAM, immagino che staresti bene finché non eseguirai molti massaggi nei gestori di eventi, ma se stai riscontrando blocchi del server, parallelLimit potrebbe essere una buona via d'uscita.

Ancora una volta, il test è il modo migliore per capire queste cose.

+0

Esperienza esattamente il blocco del server dopo 24-30 ore di lavoro dell'applicazione (anche con l'esecuzione seriale), solo una soluzione è ora riavviare l'app. Sono un fermento a causa di memoria insufficiente o qualcosa del genere (nessun errore, ma la richiesta http si blocca) .. –

+0

Sembra una perdita di memoria più di un server sovraccarico per me. Con quale frequenza gestisci il 200 task cycle per 24-30 ore? – Wyatt

+0

Molto spesso, fino a 100 volte ..Sospetto anche la perdita di memoria, ma è solo difficile affrontarla. –

0

Lo svantaggio principale che si vedrà qui è un picco nel carico del server di database. Potrebbe non essere corretto a seconda della configurazione.

Se il server di database è una risorsa condivisa, è probabile che si desideri limitare le richieste parallele utilizzando invece async.eachLimit.

3

rilevo che async.parallel esegue più funzioni contemporaneamente non (completamente) parallelamente. È più simile al parallelismo virtuale.

L'esecuzione simultanea è come l'esecuzione di programmi diversi su un singolo core della CPU, tramite multitasking/pianificazione. La vera esecuzione parallela eseguiva programmi diversi su ciascun core della CPU multi-core. Questo è importante come nodo.js ha l'architettura a filettatura singola.

La cosa migliore del nodo è che non devi preoccuparti di I/O. Gestisce l'I/O in modo molto efficiente.

Nel tuo caso stai memorizzando i dati su MongoDB, è principalmente I/O. Quindi, eseguendoli parallelamente, si utilizzerà la larghezza di banda della rete e se si legge/scrive dal disco e poi anche la larghezza di banda del disco. Il tuo server non si bloccherà a causa del sovraccarico della CPU.


La conseguenza di questo è che se si sovraccaricare il server, le richieste potrebbero non riuscire. Potresti ricevere l'errore EMFILE (Troppi file aperti). Ogni socket conta come un file. Di solito le connessioni sono raggruppate, il che significa stabilire una connessione che viene presa dal pool e al termine del ritorno alla piscina. È possibile aumentare il descrittore di file con ulimit -n xxxx.

È inoltre possibile che si verifichino errori di socket in caso di sovraccarico come ECONNRESET (Errore: riagganciamento socket), ECONNREFUSED o ETIMEDOUT. Quindi gestiscili correttamente. Controlla anche il numero massimo di connessioni simultanee per il server mongoDB.


Infine il server può riagganciare a causa della garbage collection. La raccolta dei rifiuti inizia dopo che la memoria è aumentata fino a un certo punto, quindi viene eseguita periodicamente dopo un po 'di tempo. La memoria heap massima V8 può avere circa 1,5 GB, quindi aspettatevi che GC funzioni frequentemente se la sua memoria è alta. Il nodo si bloccherà con process out of memory se si richiede più di quel limite. Quindi aggiusta le perdite di memoria nel tuo programma. Puoi guardare questi tools.

0

vi renderete conto della differenza se più utenti si collegano:

in questo caso il processore può gestire più operazioni

asincrono tenta di eseguire diverse operazioni di più utenti relativa pari

T = task 
U = user 
(T1.U1 = task 1 of user 1) 

T1.U1 => T1.U2 => T2.U1 => T8.U3 => T2.U2 => etc 

questa è l'oposite di atomicy (quindi forse guardare per atomicy su operazioni db speciali - ma questo è un altro argomento)

così m aybe è più veloce da usare:

T2.U1 before T1.U1 

- questo non è un problema fino a quando

T2.U1 is based on T1.U1 

- questo è evitabile utilizzando le richiamate/o quindi sono callback

... spero che questo è ciò che volevi sapere ... è un po 'tardi qui