venerdì 24 settembre 2010

Nginx: alfabetizziamoci con un estratto omeopatico



Provate a leggere ad alta voce, tre volte consecutive, la storia dei Tre Maialini mentre gli occhi cercano di spezzare quella tensione che tiene ancora sollevata la palpebra: la lingua diventa un blocchetto di porfido rosa.
Quando succede ciò, ci si accorge di avere un problema da risolvere, una nuova sfida da affrontare, nel mio caso: evitare di far collassare il web server, virtualizzato con 256 Mb di memoria dedicata, quando si cerca di far girare il sito dei “Tre maialini”.
I tempi di reazione di un Programmatore 2.0 rappresentano la garanzia del suo titolo acquisito, così rimedio velocemente una cura omeopatica: nginx.
Mentre la mia lingua, imbastardita dall'italiano gonfio e tronfio di vocali, si contorce nella bocca per trovare silenziosamente e timidamente la giusta forma fonetica (enghienics, nògincs, ennegienneicsete...), i sitarelli ufficiosi mi svelano che la pronuncia di quel compresso scioglilingua è un banale “engine x” ...ciò doveva illuminarmi su quello che stavo per affrontare.



L'incognito motore, alias Engine X, è sfacciatamente ritenuto la “Aspirina” dei web server. Risolve qualsiasi male (può essere usato come proxy mail), è solido, robusto, snello, efficace, veloce... e soprattutto, la sua architettura è stata pensata per dare una risposta vincente a un problema che affligge l'ignara umanità internauta: C10k problem.
Quindi consiglio a tutti di installarlo. Non si sa mai, se cadete e vi sbucciate le ginocchia potete sempre farvi una fasciatura con delle stampe dei suoi codici sorgenti.

Secondo le autorevoli stime di Netcraft, Nginx si è guadagnato il terzo posto (4,24% di share) in termini di diffusione (forse il tam tam in Rete dei suoi effetti curativi e placebo ha partecipato in parte a questo successo), diventando a tutti gli effetti la valida, snella e breve alternativa al blasonato “Apache, figlio di Apollo; Fece una palla di pelle di pollo; Tutti i pesci vennero a galla; Per vedere la palla di pelle di pollo; Fatta da Apelle figlio di Apollo”.

Come avrete sicuramente notato, Apache è uno scioglilingua obeso dalle vocali, non istiga alla violenza la nostra lingua, ma si muove con flatulenta prepotenza su server minidotati come il mio (server!!).

Arriviamo al dunque di questo post tecnico (eureka, il primo su questo blog!!) che tutti voi bramate da un Pro Pro Pro Pro (no, non è l'audio della flatulenza di Apache sul server minidotato), Provvidenziale Programmatore Professionista Provinciale, del mio calibro.


nginx: teoria e pratica

Ovviamente, per fare l'amato “uovo fuori dalla cavagna” (Di questo detto non ho mai allargato il mio bagaglio culturale cercando la definizione di “cavagna”; da una veloce ricerca in Internet il risultato mi lascia perplesso... ma compiaciuto. Happy ignoranza), ho pensato di iniziare dalla fine per rovinarvi la suspence dell'inizio.

Buon inizio

Nel mezzo del cammin di nostra vita
mi ritrovai per una selva oscura
ché la diritta via era smarrita.

(Divina Commedia)



Premessa obbligatoria


Un install nginx sarebbe sufficiente per installare questo web server, e il post ad alto contenuto tecnico sarebbe finito, purtroppo il mio minidotato server virtuale deve interpretare le pagine PHP... e qui inizia il divertimento.

La guida ufficiale di nginx si appoggia a un elenco di siti, pagine e blog di smanettoni che hanno trovato una strada funzionante; e sì, ci sono differenti metodi per far girare PHP, e ognuno si autocita dichiarandosi come “portatore di una verità assoluta”.
Ebbene, la guida per l'installazione di nginx+php+mysql+phpmyadmin “assolutamente giusta, migliore ed efficace” è scritta in questo post, non credete ad altri ;-)

Inizialmente volevo seguire la via “dichiarata giusta”, ma scoperto il dedalo di vie, ho pensato di impormi dei criteri per valutare il metodo di installazione da seguire:
  1. non compilare alcun software
  2. non usare alcun software che non sia contemplato dai repository ufficiali della distro installata sul server (Debian Squeeze 64 bit)
  3. cercare di fare il minor numero di hack (questo la dice lunga su nginx + php)
  4. e, infine, far funzionare nginx+php+mysql+phpmyadmin sul server da 256 Mb

Con questi presupposti, vi scoraggio a cercare nella grande Rete e vi incoraggio a lasciar perdere; se proprio insistete continuate a leggere qui (abbiate un po' di pazienza), che è riportato l'unico, assoluto, magnifico e funzionate “how to install: nginx php5 mysql phpmyadmin”.


I benchmark: conclusione dell'installazione

Il sito dei “Tre maialini” sta girando sul mio server virtualizzato! Fine.

Ma, adesso che tutto funziona, facciamo delle valutazioni per capire se ne è valsa la pena.
Per un veloce confronto, vista la comodità e velocità di installazione di Apache2 (no comment), ho creato un'altra macchina per eseguire il medesimo compito.

Con questo banale test verifico l'utilizzo totale della memoria consumata da tutti i servizi avviati  nei rispettivi server.
Nota: Le impostazioni di Apache, ngnix, PHP e mysql sono state lasciate con i valori di default delle reciproche installazioni.

1) -------------------------------
Stato all'avvio delle due macchine:

Nginx:      247 Mb
Apache2: 239 Mb

2) -------------------------------
Visualizzazione della prima pagina, dopo il login, di PhpMyAdmin, da parte di un'unica sessione di un browser esterno.

Nginx:      316 Mb
Apache2: 306 Mb

3) -------------------------------
Navigazione tra le pagine e query di PhpMyAdmin, da parte di tre browser esterni.

Nginx: 309 Mb
Con il seguente dettaglio dei singoli servizi avviati:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 8352 808 ? Ss 10:19 0:00 init [2]
root 212 0.0 0.1 54156 1484 ? Sl 10:19 0:00 /usr/sbin/rsyslogd -c4
101 223 0.0 0.0 23260 592 ? Ss 10:19 0:00 /usr/bin/dbus-daemon --system
root 229 0.0 0.1 49168 1156 ? Ss 10:19 0:00 /usr/sbin/sshd
root 254 0.0 0.0 3952 648 ? S 10:19 0:00 /bin/sh /usr/bin/mysqld_safe
mysql 365 0.0 2.5 236788 25952 ? Sl 10:19 0:00 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --us
root 366 0.0 0.0 3852 624 ? S 10:19 0:00 logger -t mysqld -p daemon.error
root 414 0.0 0.0 30188 956 ? Ss 10:19 0:00 nginx: master process /usr/sbin/nginx
www-data 415 0.0 0.2 30980 2308 ? S 10:19 0:00 nginx: worker process
www-data 425 0.0 0.8 131212 8436 ? Ss 10:19 0:00 /usr/bin/php5-cgi
www-data 435 0.0 1.6 140536 16248 ? S 10:19 0:00 /usr/bin/php5-cgi
www-data 436 0.0 1.6 140800 16448 ? S 10:19 0:00 /usr/bin/php5-cgi
www-data 437 0.0 1.6 140800 16288 ? S 10:19 0:00 /usr/bin/php5-cgi
www-data 438 0.0 1.4 138716 14632 ? S 10:19 0:00 /usr/bin/php5-cgi
www-data 439 0.0 1.5 139752 15472 ? S 10:19 0:00 /usr/bin/php5-cgi
www-data 440 0.0 1.6 140532 16236 ? S 10:19 0:00 /usr/bin/php5-cgi
root 484 0.0 0.0 20904 952 ? Ss 10:19 0:00 /usr/sbin/cron
root 856 0.0 0.0 18624 624 ? Ss 10:48 0:00 vzctl: pts/0
root 857 0.0 0.1 17688 1876 pts/0 Ss 10:48 0:00 -bash
root 864 0.0 0.1 14812 1040 pts/0 R+ 10:49 0:00 ps aux

Apache2: 368 Mb
Con il seguente dettaglio dei singoli servizi avviati:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 8352 808 ? Ss 10:19 0:00 init [2]
root 211 0.0 0.1 119692 1496 ? Sl 10:19 0:00 /usr/sbin/rsyslogd -c4
101 222 0.0 0.0 23260 592 ? Ss 10:19 0:00 /usr/bin/dbus-daemon --system
root 228 0.0 0.1 49168 1136 ? Ss 10:19 0:00 /usr/sbin/sshd
root 253 0.0 0.0 3952 648 ? S 10:19 0:00 /bin/sh /usr/bin/mysqld_safe
mysql 364 0.0 2.5 171240 25748 ? Sl 10:19 0:00 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --us
root 365 0.0 0.0 3852 624 ? S 10:19 0:00 logger -t mysqld -p daemon.error
root 443 0.0 0.0 20904 952 ? Ss 10:19 0:00 /usr/sbin/cron
root 460 0.0 0.9 181832 9584 ? Ss 10:19 0:00 /usr/sbin/apache2 -k start
www-data 514 0.0 1.6 189428 16800 ? S 10:19 0:00 /usr/sbin/apache2 -k start
www-data 515 0.0 1.1 184652 11872 ? S 10:19 0:00 /usr/sbin/apache2 -k start
www-data 516 0.0 1.1 184628 11344 ? S 10:19 0:00 /usr/sbin/apache2 -k start
www-data 517 0.0 1.2 185656 12828 ? S 10:19 0:00 /usr/sbin/apache2 -k start
root 572 0.0 0.0 18624 620 ? Ss 10:21 0:00 vzctl: pts/0
root 573 0.0 0.1 17688 1876 pts/0 Ss+ 10:21 0:00 -bash
www-data 584 0.0 1.8 191132 18288 ? S 10:24 0:00 /usr/sbin/apache2 -k start
www-data 585 0.0 1.5 188788 16012 ? S 10:24 0:00 /usr/sbin/apache2 -k start
www-data 588 0.0 1.6 189044 16384 ? S 10:24 0:00 /usr/sbin/apache2 -k start
www-data 589 0.0 1.1 184628 11736 ? S 10:24 0:00 /usr/sbin/apache2 -k start
www-data 731 0.0 1.2 185652 12660 ? S 10:35 0:00 /usr/sbin/apache2 -k start
root 735 0.0 0.0 18624 624 ? Ss 10:38 0:00 vzctl: pts/1
root 736 0.0 0.1 17688 1876 pts/1 Ss 10:38 0:00 -bash
www-data 895 0.0 0.6 181832 6160 ? S 10:47 0:00 /usr/sbin/apache2 -k start
www-data 896 0.0 0.6 181832 6160 ? S 10:47 0:00 /usr/sbin/apache2 -k start
www-data 897 0.0 0.6 181832 6160 ? S 10:47 0:00 /usr/sbin/apache2 -k start
root 899 0.0 0.1 14812 1032 pts/1 R+ 10:47 0:00 ps aux



La “Aspirina” (alias nginx) ha deluso le mie aspettative. Inizialmente Apache2 risulta essere più leggero, in termini di memoria occupata, rispetto al tanto esaltato nginx.
Ovviamente la dieta mediterranea di nginx si inizia ad apprezzare quando più client browser si collegano contemporaneamente al server web. Ma con una buona ottimizzazione delle impostazioni di Apache2, e considerando che a questo mio minidotato server si collegheranno al massimo 10 client, esclusivamente per gestire i pannelli di controllo sul web della macchina, e che quindi non scoprirò mai cosa sia il famigerato C10k problem, direi che lo sbattimento sotto riportato me lo sarei potuto tranquillamente risparmiare.


Chi ce lo fa fare: conclusione dell'installazione

Per chi avesse necessità di usare PHP e non avesse il timore del C10k problem, ritengo che l'acquisto di un banco di RAM per soddisfare l'ipercalorico Apache2 sia la soluzione migliore. Considerando che l'architettura di Apache nella visualizzazione delle pagina dinamiche dovrebbe essere più reattiva, oltre alla facilità di installazione, ricchezza della documentazione, vaste potenzialità e facilità e sicurezza con cui è possibile installare i più svariati siti/servizi web: phpmyadmin, wordpress, joomla, drupal, ecc...

Non mi rimane che dirvi: "perché state ancora continuando a leggere questo mio preziosissimo Manuale per l'installazione di nginx con php, mysql e phpmyadmin che segue a breve?" (abbiate ancora un po' di pazienza, il testo altamente tecnico c'è!).

ATTENZIONE: alla fine, il mio impegno nell'installare la panacea di tutti  i mali (alias nginx) non mi ha permesso di superare la sfida iniziale: evitare di far collassare il web server, virtualizzato con 256 Mb di memoria dedicata, quando si cerca di far girare il sito dei “Tre maialini”.
Ci vogliono almeno 512 Mb per far girare phpmyadmin (alias "Tre maialini")!!



How To: codesto documento ad alto contenuto tecnico tanto bramato


NB: Installazione testata su Debian Squeeze, 64 bit

Installazione nginx con php

Installare i seguenti pacchetti per avere anche il supporto php:
apt-get install nginx php5-cli php5-cgi spawn-fcgi mysql-server

Eseguire il seguente comando:


echo "console output" >> /etc/init.d/nginx


Avviare il servizio di nginx:

/etc/init.d/nginx start


Creare lo script di avvio di fastcgi per eseguire PHP:

vi /usr/bin/php-fastcgi

e scrivere all'interno del file il seguente testo:

#!/bin/sh
/usr/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -C 6 -u www-data -f /usr/bin/php5-cgi
NOTA del 15/11/10:  l'opzione -C 6 al comando sopra citato specifica di utilizzare 6 processi figli aggiuntivi per servire le pagine PHP, quest'opzione è utile per servire più connessioni. Non inserendo quest'opzione non si avranno processi figli: scelta ottimale per risparmiare memoria al sistema qualora le connessioni fossero ridotte.

Attribuire i corretti permessi al file creato:
chmod a+x /usr/bin/php-fastcgi

Creare lo script per la gestione automatica del servizio:

vi /etc/init.d/php-fastcgi

e scrivere all'interno del file il seguente testo:

#!/bin/bash
### BEGIN INIT INFO
# Provides: php-fastcgi
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start and stop php-cgi in external FASTCGI mode
# Description: Start and stop php-cgi in external FASTCGI mode
### END INIT INFO
PHP_SCRIPT=/usr/bin/php-fastcgi
FASTCGI_USER=www-data
RETVAL=0
case "$1" in
start)
   su - $FASTCGI_USER -c $PHP_SCRIPT
   RETVAL=$?
   ;;
stop)
   killall -9 php5-cgi
   RETVAL=$?
   ;;
restart)
   killall -9 php5-cgi
   su - $FASTCGI_USER -c $PHP_SCRIPT
   RETVAL=$?
   ;;
*)
   echo "Usage: php-fastcgi {start|stop|restart}"
   exit 1
   ;;
esac
exit $RETVAL
console output

Attribuire i corretti permessi al file creato:
chmod 755 /etc/init.d/php-fastcgi


Permettere l'avvio automatico dello script:
update-rc.d php-fastcgi defaults


Avviare il servizio:
/etc/init.d/php-fastcgi start


Per permettere la lettura delle pagine php è necessario modificare le impostazioni del dominio. Nel mio caso, ospitando un solo dominio, utilizzo il file di configurazione del dominio di default.

vi /etc/nginx/sites-available/default

e aggiungere le seguenti righe:
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {

    #FIX verifico l'esistenza del file richiesto per evitare falle di sicurezza
    if (!-f $request_filename) {
     return 404;
    }

    root /var/www;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include fastcgi_params;
 }


NOTA: Il FIX è stato aggiunto a causa della presenza di una falla di sicurezza in FastCGI: qui potete trovare maggiori informazioni a riguardo.

Inoltre è possibile specificare la directory di root dei siti web e indicare le pagine index di default; ecco un esempio:

location / {
  root /var/www;
  index index.html index.htm;
  fastcgi_index  index.php;
}


Per verificare in funzionamento creare una pagina php di prova:
vi /var/www/index.php

e scrivere dentro il seguente testo:






Successivamente navigare all'indirizzo del server (ES: http://indirizzoIP/index.php ) con un browser per testare se la pagina php viene letta correttamente.
Dovreste visualizzare una pagina simile a questa:


Installazione phpmyadmin

Purtroppo non è stato facile capire come fare, senza caricare phpmyadmin nella document root del web. Ma è possibile seguendo questa guida:

Installare il pacchetto dai repository :
apt-get install phpmyadmin

verranno fatta delle domande, nella lista dei server web non compare nginx (e te pareva!), pertanto ho selezionato casualmente apache (ma credo sia meglio non seleziona nulla).

Finita l'installazione per fare funziona phpmyadmin all'indirizzo http://localhost/phpmyadmin, visto che non c'è l'installazione dedicata per nginx, bisogna procedere con i seguenti passi:

Aprire il file di configurazione del dominio (continuo ad usare quello di default):
vi /etc/nginx/sites-available/default

e aggiungere le seguenti righe:

        location /phpmyadmin {
                root /usr/share;
                fastcgi_index  index.php;
               index index.php;
        }
        location ~ ^/phpmyadmin.+.php$ {
                root /usr/share;
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                include fastcgi_params;
        }




Infine riavviate i servizi:
/etc/init.d/nginx reload
/etc/init.d/php-fastcgi restart

e provate a collegarvi all'indirizzo http://indirizzoIP/phpmyadmin. Buona navigazione.


Ringraziamenti

Questa preziosissima guida è frutto di: un abile copia e incolla, imprecazioni (tante), prove e cocciutaggine personale.
Pertanto si ringrazia tutti quelli che hanno nascosto una traccia importante nelle loro guide o quelli che avevano esigenze chiaramente diverse dalle mie... o guide per altre piattaforme.

Vorrei citare tutte le possibili fonti, ma essendo troppe e di breve ispirazione cito un semplice grazie!

6 commenti:

  1. Sorry , ma l'originale " Con Erbe Della Puszta " l'ho io , l'effetto catartico è assicurato , per il resto..ai posteriori l'ardua sentenza.
    Bye Bye

    RispondiElimina
  2. A quando l'intervista a Rachida Dati ?

    http://www.lastampa.it/multimedia/multimedia.asp?IDmsezione=10&IDalbum=30257&tipo=VIDEO

    RispondiElimina
  3. ... e pensare che l'uovo fuori dalla cavagna lo si utilizza anche dalle mie parti, ma come "fa l'öf fö da la cavagna" ! Così definiremmo nginx ;-)

    RispondiElimina
  4. Nginx è ottimo, in base alla configurazione che gli dai, sia nel vhost che nella main config si comporta in maniera diversa. Se ti ha deluso evidentemente hai usato la configurazione di default.

    RispondiElimina
  5. Mi ha "deluso" perché come cura omeopatica per la riduzione dell'uso di RAM nella gestione di alcune interfacce web (PHP) che hanno un numero massimo di visitatori unici pari a 10 è stata inefficace.
    Ho sudato come un polpo bagnato per scoprire che tale impegno potevo risparmiarmelo.

    Per par condicio sia Apache2, Lighttpd e Nginx, sono stati mantenuti con la configurazione originaria durante il mio test di comparazione. Certamente avrei potuto ottenere dei risultati migliori, ma lo stesso vale anche per gli altri web server (in particolare Apache).

    Comunque sono sicuro che nginx sia un ottimo prodotto, difatti l'ho sto usando in uno dei server virtualizzati, ma non ritengo che l'esser parsimonioso di risorse nell'uso di banali interfacce web da amministratore sia il suo cavallo di battaglia.

    RispondiElimina
  6. Con varie ottimizzazioni nginx+php+mysql+proftpd e i restanti processi sistema, allo startup ho meno di 160 mb

    RispondiElimina