Alcuni benchmarks
medio
Hardware e configurazione del sistema usato per i test
Il test è stato effettuato su questa configurazione:
Intel Pentium Dual CPU (E2140) a 1.60GHz (dual core) equipaggiato con 512 MB di ram (di cui 64MB condivisi con la scheda video).
La distribuzione utilizzata è una Debian Etch con apache versione 2.2.3 e Nginx versione 0.6.32.
Tuning dei web server
Ho configurato i server per servire la stessa pagina statica.
Apache
La configurazione di default di apache è piuttosto conservativa: questo per evitare di far collassare il server se sottoposto ad un numero eccessivo di richieste.
Per effettuare i test ho dovuto quindi modificare alcuni parametri:
MaxKeepAliveRequest 0
La configurazione di default permette un massimo di 100 connessioni keep-alive (0 significa connessioni infinite).
Su Debian Apache viene configurato in compilazione per l'utilizzo del motore mod_prefork (un processo per ogni connessione). Ho modificato i seguenti parametri:
ServerLimit 1000 MaxClient 1000
in questo modo dovrebbe gestire fino a 1000 connessioni.
Il numero di client gestibile da Apache è pari a
maxclient = ram disponibile/ram occupata singolo processo
Nginx
Le uniche modifiche su Nginx sono:
worker_processes 2
Con questa voce vengono creati due processi master. In questo modo posso sfruttare i due core del processore.
worker_connection 1024
Con questo parametro vengono configurate il numero massimo di connessioni per ogni processo master.
La formula per calcolare il numero massimo di client è
maxclient = worker_processes * worker_connection
Nella configurazione reverse-proxy si usa una formula un po' diversa:
maxclient = worker_processes * worker_connection / 4
in quanto i browser aprono di default 2 connessioni al server e Nginx ne apre altrettante per collegarsi al backend.
Modalità di test
Ho utilizzato Apache bench per sottoporre i web server ad un certo numero di richieste ed ho raccolto i dati con vmstat.
Apache bench (ab) fa parte del pacchetto apache2-util. E' un semplice tool a riga di comando che esegue, per un determinato numero di secondi, la richiesta di un url utilizzando un determinato numero di connessioni concorrenti.
Le opzioni utilizzate sono queste:
ab -kc numeroconnessioniconcorrenti -t secondi http://webserver/
Secondo le configurazione di default ab effettua un massimo di 50000 richieste http dopodiché termina.
Ho utilizzato l'opzione k, che prevede connessioni keep-alive, in quanto mi interessava mostrare la differente gestione delle connessioni tra i due programmi.
Attenzione: ab crea un certo numero di socket consumando i descrittori di file disponibili nel sistema. Per oltrepassare le 800 richieste concorrenti è stato necessario aumentare il numero dei descrittori con il comando "ulimit -n 2000".
Con vmstat ho raccolto i dati sul sistema in esame.
In sostanza sul pc client ho lanciato ab per 60 secondi con vari livelli di concorrenza.
Sul pc server ho lanciato vmstat 1 60 (output ogni secondo per 60 secondi).
Risultati dei test
Apache ha retto con 200 e 400 richieste concorrenti: da 500 in poi non è riuscito a raggiungere le 20000 risposte (sulle 50000).
Nginx invece ha retto senza errori fino a 1000 richieste concorrenti: oltre le 1000 continua a rispondere a tutte le richieste fallendone qualcuna.
Ad esempio su 1500 richieste concorrenti ha risposto correttamente 49819 volte (su 50000).
Come tempi di risposta tra i due programmi non ci sono evidenti differenze: crescono in modo proporzionale alla concorrenza delle richieste.
Controllando le risorse impiegate emergono dei dati molto interessanti:
Sotto il profilo della cpu emerge grosso modo che Nginx ne usa la metà di Apache.
In questo grafico confronto la percentuale di cpu di Apache con 200 e 400 connessioni concorrenti e Nginx con 200 e 1000 connessioni. Un aspetto evidente è che il consumo di cpu risulta indipendente dal livello di concorrenza (sarebbe interessante provare ad aumentare i worker_processes di Nginx per vedere se le performance aumentano).
Per quanto riguarda la ram si evidenzia la maggior occupazione di apache per singola connessione. Questo porta l'occupazione di ram a salire in modo repentino.
Dal grafico si evince che su Apache con oltre 400 connessioni concorrenti la memoria libera finisce in fretta e la memoria virtuale non riesce a gestire il flusso di richieste. Questo spiega l'interruzione delle risposte.
I dati raccolti confermano la differenza tecnologica tra i due prodotti: la creazione di un nuovo processo per ogni nuova connessione porta Apache ad occupare eccessive risorse. Per contro Nginx, grazie alla sua struttura asincrona, risulta molto più scalabile.
Conclusioni
Riporto alcuni casi d'uso trovati su internet:
- reverse proxy, load balancer (ad esempio wordpress)
- reverse proxy di Apache per servire file statici (vedi qui)
- come imap/pop proxy (fastmail.fm)
In definitiva, a mio parere, l'utilizzo di Nginx può essere una valida alternativa in siti ad alto traffico.