Come suggerisce il titolo della domanda, sto facendo fatica a capire cosa può essere migliorato nella mia applicazione (o ottimizzato nel sistema operativo, Ubuntu) per ottenere prestazioni accettabili. Ma prima spiegherò l'architettura:
Il server front-end è una macchina a 8 core con 8 GB di RAM con Ubuntu 12.04. L'applicazione è scritta interamente in javascript ed eseguita in node.js v 0.8.22 (poiché alcuni moduli sembrano lamentarsi delle versioni più recenti del nodo) Uso nginx 1.4 per eseguire il proxy del traffico http dalla porta 80 e 443 agli operatori a 8 nodi gestiti e ha iniziato a utilizzare l'API del cluster di nodi. Uso l'ultima versione di socket.io 0.9.14 per gestire le connessioni socket web, su cui ho abilitato solo websocket e polling xhr come trasporti disponibili. Su questa macchina eseguo anche un'istanza di Redis (2.2)
Archivo dati persistenti (come utenti e punteggi) su un secondo server su mongodb (3.6) con 4 GB di RAM e 2 core.
L'app è in produzione da alcuni mesi (è stata eseguita su una singola scatola fino a poche settimane fa) ed è utilizzata da circa 18.000 utenti al giorno. Ha sempre funzionato molto bene a parte un problema principale: il degrado delle prestazioni. Con l'uso, la quantità di CPU utilizzata da ciascun processo aumenta fino a quando non staturizza il lavoratore (che non servirà più le richieste). L'ho risolto temporaneamente controllando la CPU in uso da ogni lavoratore ogni minuto e riavviandola se raggiunge il 98%. Quindi il problema qui è principalmente CPU, non RAM. La RAM non è più un problema da quando ho aggiornato socket.io 0.9.14 (la versione precedente perdeva memoria), quindi dubito che si tratti di un problema di perdita di memoria, soprattutto perché ora è la CPU che cresce abbastanza rapidamente ( Devo riavviare ogni lavoratore circa 10-12 volte al giorno!). La RAM in uso cresce anche a dire il vero, ma molto lentamente, 1 concerto ogni 2-3 giorni di utilizzo e la cosa strana è che non viene rilasciato anche quando riavvio completamente l'intera applicazione. Viene rilasciato solo se riavvio il server! questo non riesco davvero a capire ...
Ora ho scoperto nodefly che è sorprendente, quindi posso finalmente vedere cosa sta succedendo sul mio server di produzione e sto raccogliendo dati da un paio di giorni. Se qualcuno vuole vedere i grafici posso darti l'accesso, ma in fondo posso vedere 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 oscilla tra 500 e 1500 millisecondi, che penso sia davvero molto. Inoltre, proprio in questo momento con 1300 utenti online, questo è 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
il che dimostra che ho un sacco di connessioni chiuse in attesa del tempo. Ho aumentato il numero massimo di file aperti 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
Quindi ho pensato che il problema potesse riguardare il traffico http che per alcuni motivi satura le porte / socket disponibili (?), Ma una cosa non ha senso per me: perché quando riavvio i lavoratori e tutti i client si riconnettono in pochi secondi, il carico sulla cpu del lavoratore scende all'1% ed è in grado di soddisfare correttamente le richieste fino a quando non si satura dopo circa 1 ora (all'ora di punta)?
Sono principalmente un programmatore javascript, non un amministratore di sistema, quindi non so quanto carico dovrei 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, poiché ovviamente porteranno più carico e alla fine andranno in crash tutto!
Spero che ci sia qualcosa di ovvio che sto sbagliando, e qualcuno aiuterà a individuarlo ... sentiti libero di chiedermi ulteriori informazioni, e mi dispiace per la lunghezza della domanda, ma era necessario, credo ... Grazie in anticipo!
top
quando l'utilizzo della cpu è vicino al 100%?