Nel precedente articolo abbiamo visto come installare e configurare il web server Lighttpd per poter fornire pagine statiche; in questo vedremo come modificare la configurazione del server per renderlo interattivo ed offrire contenuti dinamici, in particolare utilizzando script PHP.
Innanzitutto va fatta un'importante premessa: diversamente da quanto comunemente accade con Apache (per lo meno in ambiente *nix) PHP non funziona come modulo di lighttpd. Lo standard adottato per il supporto a PHP è FastCGI. Per chiarire un po' le idee ricordo sinteticamente che, una delle prime tecniche adottate per rendere i contenuti web dinamici fu CGI, Common Gateway Interface. Sostanzialmente uno standard che consentiva ad un server http di comunicare con un'applicazione esterna scritta in un linguaggio qualunque. Tra i vantaggi di questo approccio vi erano sicuramente semplicità, isolamento di processi (l'applicazione girando come processo separato non può mandare in crash il server), indipendenza dall'architettura. Purtroppo per ogni richiesta da parte di un client, il server crea un nuovo processo, il processo deve inizializzarsi, eseguire le operazioni di comunicazione dei dati attraverso standard input/output ed infine terminare chiudendo la richiesta. Tutto il meccanismo impegna notevoli risorse e limita pesantemente il numero di connessioni gestibili contemporaneamente.
Per sopperire a tale manchevolezza Open Market sviluppò la tecnologia FastCGI rendendola poi pubblica. In questo caso i processi sono persistenti e, terminata una richiesta, rimangono in attesa della successiva anziché chiudersi, eliminando i tempi connessi a fork, startup e cleanup. Mentre la comunicazione tra web server e programmi CGI avviene tramite pipe, i processi FastCGI usano un socket unix o una connessione TCP/IP. Un notevole vantaggio di quest'approccio è che il programma può essere eseguito su una macchina remota, con privilegi diversi dal web server ed eventualmente in una propria gabbia di chroot.
Malgrado i miglioramenti persiste comunque una proliferazione di processi, tuttavia il team di sviluppo di Lightppd sostiene di aver ottenuto migliori prestazioni rispetto ad Apache 1.3.x + mod_php4 e fornisce sul proprio sito i risultati dei test.
PHP e FastCGI
Riprendendo le fila del precedente articolo ricordo che abbiamo cominciato i nostri esperimenti utilizzando una Linux box Fedora Core 6, appoggiandoci a Yum per l'installazione dei pacchetti necessari. Per poter utilizzare PHP quest'ultimo deve essere installato con il supporto FastCGI. Le principali pacchettizzazioni prevedono php-cgi facilitando di molto la vita, se invece preferite la compilazione dai sorgenti le opzioni minimali da usare sono:
./configure --enable-fastcgi --enable-discard-path --enable-force-redirect
A queste dovrete aggiungere tutte quelle risultanti dall'output di php_info()
se volete mantenere le medesime caratteristiche con cui lo state attualmente usando come modulo di Apache.
Ma torniamo a noi, per verificare che sulla nostra Fedora Core 6 ci troviamo nelle condizioni ideali digitiamo:
# php-cgi -v
PHP 5.1.6 (cgi-fcgi) (built: Oct 4 2006 11:12:18)
Copyright (c) 1997-2006 The PHP Group
Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies
with eAccelerator v0.9.5, Copyright (c) 2004-2006 eAccelerator, by eAccelerator
Una risposta simile a quella riportata immediatamente sotto al comando, in cui è visibile la stringa evidenziata in rosso cgi-fcgi, ci garantisce il supporto.
Individuiamo ora la posizione dell'eseguibile che dovremo utilizzare in fase di configurazione:
# which php-cgi /usr/bin/php-cgi
Infine un giro di ricognizione nella directory dei moduli /usr/lib/lighttpd/ ci rivela che il pacchetto precedentemente installato, lighttpd.i386, non include il modulo FastCGI. Niente paura, ricorriamo all'aiuto di yum usando la wildcard *:
# yum list lighttpd*
Scopriamo due ulteriori pacchetti: lighttpd-fastcgi.i386 e lighttpd-mod_mysql_vhost.i386. Il primo certamente farà al caso nostro installiamolo, dunque, con il comando:
# yum install lighttpd-fastcgi
Configuriamo Lighttpd
Per comodità riporto di seguito la configurazione minimale che avevamo adottato nel precedente articolo per servire solo pagine statiche. A partire da questa apporteremo le modifiche necessarie per poter eseguire script PHP.
server.modules = ( "mod_accesslog" ) server.username = "lighttpd" server.groupname = "lighttpd" server.port = 3000 server.pid-file = "/var/run/lighttpd.pid" server.document-root = "/srv/www/lighttpd/" accesslog.filename = "/var/log/lighttpd/access_log" server.errorlog = "/var/log/lighttpd/error_log" index-file.names = ( "index.html", "index.htm", "default.htm" ) static-file.exclude-extensions = ( ".php", ".pl", ".fcgi","~", ".inc" ) mimetype.assign = ( ".pdf" => "application/pdf", ".mp3" => "audio/mpeg", ".ogg" => "application/ogg", ".gif" => "image/gif", ".jpg" => "image/jpeg", ".jpeg" => "image/jpeg", ".png" => "image/png", ".html" => "text/html", ".htm" => "text/html", ".text" => "text/plain", ".txt" => "text/plain", ".dtd" => "text/xml", ".xml" => "text/xml", ".mpeg" => "video/mpeg", ".mpg" => "video/mpeg", )
Prima di tutto dobbiamo caricare all'avvio il modulo mod_fastcgi
e quindi modificare la direttiva server.modules
nel modo seguente:
server.modules = ( "mod_accesslog", "mod_fastcgi" )
Mettiamo mano anche a index-file.names
per aggiungere index.php all'elenco dei file di indice:
index-file.names = ("index.php", "index.html", "index.htm", "default.htm" )
Veniamo infine alla direttiva fondamentale fastcgi.server
:
fastcgi.server = ( ".php" => ( "localhost" => ( "socket" => "/tmp/php-fastcgi.socket", "bin-path" => "/usr/bin/php-cgi" ) ) )
A questo punto modifichiamo il file php.ini aggiungendo la riga:
cgi.fix_pathinfo = 1
Dovremmo ormai esserci: riavviamo il server
# service lighttpd restart
se non vengono segnalati errori di sintassi verifichiamone il corretto funzionamento inserendo nella document root /srv/www/lighttpd/ la pagina index.php contenente il codice <? echo "ciao mondo" ?>. Apriamo il browser e nella barra dell'indirizzo digitiamo http://localhost:3000/ (ricordo che in questa fase sperimentale abbiamo messo il web server in ascolto sulla porta 3000).
La comparsa della pagina con la stringa ciao mondo ci segnalerà che tutto funziona alla perfezione! Attenzione, se non avete inserito in index-file.names per prima index.php, al suo posto vi risponderà la pagina di default di Lighttpd, index.html. Basterà in tal caso forzarne la richiesta: http://localhost:3000/index.php.
Analizziamo la direttiva fastcgi.server
Nell'esempio abbiamo impostato la direttiva con un numero di parametri minimo giusto per garantirci il funzionamento di PHP. Il primo elemento .php stabilisce l'estensione dei file, dopo abbiamo indicato l'hostname (potrebbe essere il numero IP) del server FastCGI, localhost, cui abbiamo associato la posizione della unix socket, con socket, ed il path dell'eseguibile, con bin-path. Come si nota la struttura ad array della direttiva la rende molto flessibile ed adatta ad implementare diverse fattispecie di configurazione.
Si può specificare un handler per ciascuna estensione di file ed inoltre realizzare un load-balancing indicando diversi handler per la medesima estensione. Il server FastCGI non deve necessariamente girare sul medesimo host del web server e Lighttpd permette con molta semplicità il forward delle richieste:
fastcgi.server = ( ".php" => (( "host" => "192.168.1.1", "port => "8080" )) )
La direttiva prevede molti altri parametri per il tuning del funzionamento tra cui possiamo citare min-procs e max-procs per impostare rispettivamente il numero minimo e massimo di processi da avviare ed idle-timeout che stabilisce il numero di secondi di attesa prima che un processo inutilizzato venga terminato. Per una descrizione completa fate riferimento alla documentazione ufficiale.
Altre due direttive sono strettamente collegate a fastcgi.server:
fastcgi.debug = 1 fastcgi.map-extensions = ( ".php3" => ".php" )
La prima stabilisce il livello di debug, al momento i valori possibili sono 0, per disabilitarlo, ed 1 per abilitarlo. La seconda mappa diverse estensioni sul medesimo server FastCGI.
Conclusioni
In questo articolo abbiamo visto come completare l'installazione e la configurazione di Lighttpd per consentire l'utilizzo di PHP, sottolineando come il Web server preveda genericamente un'interfaccia verso programmi esterni che supportino lo standard FastCGI. Quanto descritto non vuole essere esaustivo bensì una base di partenza per poter creare e sperimentare le proprie configurazioni con l'aiuto della documentazione e del file lighttpd.conf predefinito.
Invito alla riflessione su alcune caratteristiche quali il risparmio di ram e cpu, il load balancing nativo su più server che potrebbero incuriosire chi si trovi a gestire situazioni critiche caratterizzate da un alto numero di connessioni parallele.