node.js, mongodb, redis, sul degrado delle performance ubuntu nella produzione, RAM è libera, CPU 100%

Come suggerisce il titolo delle domande, ho difficoltà a capire cosa possa essere migliorata sulla mia applicazione (o sintonizzata nell'ottomassa, ubuntu) per get una prestazione accettabile. Ma prima spiegherò l'architettura:

Il server front-end è una macchina da 8 core con 8 gig RAM di Ubuntu 12.04. L'applicazione è scritta interamente in javascript e viene eseguita in node.js v 0.8.22 (poiché alcuni moduli sembrano lamentarsi sulle nuove versioni del nodo) utilizzo il traffico http da nginx 1.4 a http da port 80 e da 443 a 8 lavoratori di nodes gestiti e ha iniziato ad utilizzare il cluster di nodes api. Utilizzo la versione più recente di socket.io 0.9.14 per gestire le connessioni websocket, su cui ho abilitato solo websockets e polling xhr come i trasporti disponibili. Su questa macchina ho anche eseguito un'istanza di Redis (2.2)

Memorizzo dati persistenti (come utenti e punteggi) su un secondo server su mongodb (3.6) con 4 gig RAM e 2 core.

L'applicazione è in produzione da pochi mesi (è in esecuzione su una singola scatola fino a poche settimane fa) e viene utilizzata da circa 18 utenti al giorno. Ha sempre lavorato molto bene a parte un problema principale: degrado delle performance. Con l'uso, la quantità di CPU utilizzata da ciascun process cresce fino a staturizzare il lavoratore (che non servirà più le richieste). Ho temporaneamente risolto il controllo della CPU in uso da each lavoratore each minuto e riavviato se raggiunge il 98%. Quindi il problema qui è principalmente CPU e non RAM. La RAM non è più un problema dato che ho aggiornato a socket.io 0.9.14 (la versione precedente ha perduto la memory), quindi dubito che sia un problema di perdita di memory, soprattutto perché ora è la CPU che cresce abbastanza rapidamente ( Devo riavviare each lavoratore circa 10-12 volte al giorno!). La RAM in uso cresce anche per essere onesto, ma molto lento, 1 gig each 2-3 giorni di utilizzo, e la cosa strana è che non viene rilasciata neanche quando riavvii completamente l'intera applicazione. Viene rilasciato solo se riavvii il server! questo non capisco davvero …

Ora ho scoperto la nodefly che è incredibile, quindi posso finalmente vedere cosa sta succedendo nel mio server di produzione e raccolgo i dati da un paio di giorni. Se qualcuno vuole vedere i grafici che ti posso accedere, ma in fondo vedo che ho tra 80 e 200 connessioni simultanee! Mi aspettavo che node.js gestisse migliaia, non centinaia di richieste. Anche il tempo medio di risposta per il traffico http varia tra i 500 ei 1500 millisecondi che credo sia veramente molto. Inoltre, in questo momento con 1300 utenti in linea, questa è l'output di "ss -s":

Total: 5013 (kernel 5533) TCP: 8047 (estab 4788, closed 3097, orphaned 139, synrecv 0, timewait 3097/0), ports 0 Transport Total IP IPv6 * 5533 - - RAW 0 0 0 UDP 0 0 0 TCP 4950 4948 2 INET 4950 4948 2 FRAG 0 0 0 

che dimostra che ho un sacco di connessioni chiuse nel tempo. Ho aumentato i file aperti max a 999999, ecco l'output di ulimit -a:

 core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 63724 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 999999 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 63724 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 

Così ho pensato che il problema potrebbe essere sul traffico http che per alcuni motivi satura le porte / socket disponibili (?), Ma una cosa non ha senso per me: perché quando riavvii i lavoratori e tutti i client si riconnettono in pochi secondi, il carico sulla CPU del lavoratore scende all'1% ed è in grado di fornire le richieste correttamente fino a saturarsi dopo circa un'ora (all'ora di punta)?

Io sono principalmente un programmatore javascript, non un amministratore sys, quindi non so quanto carico potrei aspettarmi di gestire con i miei server, ma sicuramente non funziona come dovrebbe. L'applicazione è stabile altrimenti e questo ultimo problema mi impedisce di spedire le versioni mobili dell'app che sono pronte, come ovviamente porteranno più carico e alla fine cadranno tutto!

Speriamo che ci sia qualcosa di ovvio che sto facendo del male e qualcuno aiuterà a scoprirlo … non esitate a chiedermi ulteriori informazioni e mi dispiace per la lunghezza della domanda, ma è necessario credere … Grazie in anticipo!

  • mod_rpaf problemi con Nginx front, Apache back-end dopo l'aggiornamento di Ubuntu
  • Scegliere "stack" per l'hosting di posta elettronica
  • 3 Server, è questo un cluster?
  • Come posso permettere ai miei utenti di impostare le impostazioni PHP.ini per wordpress?
  • Risoluzione dei problemi di performance del disco IO scarse
  • Perché nf_conntrack_count continua a crescere?
  • La latenza di Ubuntu HTTP che cade in quantili strani
  • Gestire in modo efficace 2+ milioni di file
  • 3 Solutions collect form web for “node.js, mongodb, redis, sul degrado delle performance ubuntu nella produzione, RAM è libera, CPU 100%”

    Dopo pochi giorni di prove e errori intensi, sono contento di poter dire che ho capito where è il collo di bottiglia, e lo metterò qui in modo che altre persone possano trarre beneficio dalle mie conclusioni.

    Il problema sta nel collegamento pub / sub che stavo usando con socket.io, e in particolare nel RedisStore utilizzato da socket.io per gestire la comunicazione interprocedura di istanze socket.

    Dopo aver capito che potrei implementare facilmente la mia versione di pub / sub usando redis, ho deciso di provarlo e di aver rimosso il redisStore da socket.io, lasciandolo con il negozio di memory predefinito (non devo trasmettere tutti i client connessi ma solo tra due diversi utenti collegati possibilmente su processi diversi)

    Inizialmente ho dichiarato solo 2 connessioni globali di redis per il trattamento del pub / sub su each client connesso e l'applicazione stava usando less risorse, ma ero ancora interessata da una costante crescita della CPU, quindi non era molto cambiato. Ma ho deciso di provare a creare due nuove connessioni a redis per each client per gestire il proprio pub / sub solo nelle sessioni, quindi chiudere le connessioni una volta che l'utente è scollegato. Poi dopo un giorno di utilizzo in produzione, la CPU era ancora a 0-5% … bingo! nessun process si riavvia, nessun bug, con le performance che mi aspettavo di avere. Ora posso dire che le rocce di node.js sono felice di averlo scelto per build questa applicazione.

    Fortunatamente redis è stato progettato per gestire molte connessioni simultanee (diversamente da mongo) e per impostazione predefinita è impostato a 10k, che lascia spazio a circa 5k utenti concorrenti, su un'unica istanza redis, che è sufficiente per il momento per me, ho letto che può essere spinto fino a 64k connessioni simultanee, quindi questa architettura dovrebbe essere abbastanza solida credo.

    A questo punto pensavo di implementare una sorta di pool di connessioni a redis, per ottimizzarla un po 'più, ma non sono sicuro se questo non provocherà nuovamente gli events pub / sub per build le connessioni, a less che ognuno di loro viene distrutta e ricreata each volta, per pulirle.

    Comunque, grazie per le tue risposte, sarò curioso di sapere cosa ne pensi e se hai qualche suggerimento.

    Saluti.

    Hai qualche codice sorgente da scaricare? Possono essere collegamenti al database non chiuso? Processi in attesa di connessioni HTTP che non si chiudono mai.

    Puoi submit alcuni log?

    Fai un PS -ef e assicuratevi che nulla sia ancora in esecuzione. Ho visto i processi web lasciare zombie che non moriranno finché non si fa un kill -9. A volte l'arresto non funziona o non funziona in modo completo e quei thread o processi conterranno RAM e talvolta CPU.

    Potrebbe essere un ciclo infinito da qualche parte nel codice o un process in crash che tiene in cima una connessione db.

    Quali moduli NPM utilizzano? Sono tutti i più recenti?

    Stai percependo delle eccezioni? Vedi: http://geoff.greer.fm/2012/06/10/nodejs-dealing-with-errors/ Vedi: https://stackoverflow.com/questions/10122245/capture-node-js-crash-reason

    Suggerimenti generali:

    http://clock.co.uk/tech-blogs/preventsng-http-raise-hangup-error-on-destroyed-socket-write-from-crashing-your-nodejs-server

    http://blog.nodejitsu.com/keep-a-nodejs-server-up-with-forever

    http://hectorcorrea.com/blog/running-a-node-js-web-site-in-production-a-beginners-guide

    https://stackoverflow.com/questions/1911015/how-to-debug-node-js-applications

    https://github.com/dannycoates/node-inspector

    http://elegantcode.com/2011/01/14/taking-baby-steps-with-node-js-debugging-with-node-inspector/

    Non una risposta in sé, in quanto la tua domanda è più di una storia che di una domanda di risposta a una risposta.

    Solo per dire che ho costruito con successo un server node.js con socket.io che gestisce oltre un milione di connessioni persistenti con una media di payload media di 700 byte.

    La scheda di interface di networking a 1Gbps stava saturando all'inizio e stavo vedendo un LOTTO di I / O attendere dagli events di pubblicazione a tutti i client.

    La rimozione di nginx dal ruolo di proxy è stata anche una memory preziosa, poiché raggiungere un milione di connessioni persistenti con un solo server è un lavoro duro di configuration, applicazione e sintonizzazione dei parametri OS. Tieni presente che è ansible solo con un sacco di RAM (circa 1M connessioni websockets mangia circa 16GB di RAM, con node.js, penso che utilizzando sock.js sarebbe ideale per il consumo di memory ridotta, ma per ora socket.io consuma molto).

    Questo collegamento è stato il mio punto di partenza per raggiungere quel volume di connessioni con il nodo. Oltre ad essere un'applicazione Erlang, tutto il tuning OS è praticamente agnostico e dovrebbe essere utile da chiunque desideri un sacco di connessioni persistenti (websockets o long-polling).

    HTH,

    Suggerimenti per Linux e Windows Server, quali Ubuntu, Centos, Apache, Nginx, Debian e argomenti di rete.