La prima versione del server Apache HTTP è stata ri­la­scia­ta nel 1995. Ancora oggi, più di 20 anni dopo, il software risulta il prin­ci­pa­le web server, anche se non manca la con­cor­ren­za. So­prat­tut­to il web server russo NGINX (pro­nun­cia­to come “Engine X“), a sua volta un progetto open source, conquista una buona fetta di mercato e a una velocità sempre più crescente. Par­ti­co­lar­men­te doloroso per la Apache Foun­da­tion: la maggior parte dei siti che se la cavano bene nell’Alexa ranking uti­liz­za­no NGINX, come mostra una sta­ti­sti­ca re­go­lar­men­te ag­gior­na­ta di W3Techs. Ma non sono solo i giganti russi di Internet, come i motori di ricerca Rambler e Yandex, il servizio e-mail Mail.RU o il social network VK, a basarsi su questo web server leggero; anche siti in­ter­na­zio­na­li come Dropbox, Netflix, WordPress e FastMail.com uti­liz­za­no NGINX per mi­glio­ra­re la per­for­man­ce dei loro servizi. Il server Apache HTTP ha quindi fatto il suo tempo?

N.B.

Il server Apache HTTP è un progetto software che viene portato avanti dalla Apache Foun­da­tion. Il nome del web server viene so­li­ta­men­te ab­bre­via­to con “Apache” dalla comunità di Internet. Anche noi seguiamo questa con­ven­zio­ne: quindi quando qui parliamo di “Apache” è inteso sempre il software e non il pro­dut­to­re.

La sfida del web 2.0

Owen Garrett, Head of Products a Nginx, Inc. descrive il web server Apache in un articolo del blog del 9 ottobre 2015 come “backbone” (let­te­ral­men­te “colonna ver­te­bra­le”) del web 1.0 e mette in evidenza la sua im­por­tan­za per lo sviluppo di Internet alle porte degli anni 2000. Il grande successo del web server sarebbe ri­con­du­ci­bi­le so­prat­tut­to all’ar­chi­tet­tu­ra semplice del software, basata su delle scelte di design che si orien­ta­va­no al World Wide Web dell’epoca, diverso dalla sua evo­lu­zio­ne odierna. Infatti 20 anni fa le pagine web erano so­stan­zial­men­te create in maniera più semplice, la banda larga era ridotta e costosa, mentre il tempo di calcolo della CPU era pro­por­zio­nal­men­te con­ve­nien­te.

Oggi abbiamo a che fare con un World Wide Web di seconda ge­ne­ra­zio­ne e ciò mostra un lato com­ple­ta­men­te dif­fe­ren­te: il numero degli utenti si è mol­ti­pli­ca­to, come anche il traffico web mondiale. Lo stesso vale per le di­men­sio­ni medie delle pagine web in rete e per il numero dei com­po­nen­ti che un browser deve ri­chie­de­re e di cui deve fare il rendering per poterli vi­sua­liz­za­re. Una parte sempre più ampia della community di Internet è cresciuta con le pos­si­bi­li­tà offerte dal Web 2.0, perciò non è abituata ad aspettare diversi secondi o ad­di­rit­tu­ra minuti per il ca­ri­ca­men­to di una pagina.

Negli ultimi anni questi sviluppi hanno posto il server Apache HTTP sempre di fronte a delle sfide. Owen Garrett ritiene perciò re­spon­sa­bi­le l’ar­chi­tet­tu­ra basata sul processo di Apache, che non può essere ben scalata per quanto riguarda il traffico crescente. Questa vul­ne­ra­bi­li­tà è stata una delle prin­ci­pa­li mo­ti­va­zio­ni per lo sviluppo di NGINX nel 2002 che con un’ar­chi­tet­tu­ra event-driven (let­te­ral­men­te “guidata dagli eventi”) propone delle altre vie. NGINX è stato creato dallo svi­lup­pa­to­re russo di software Igor Sysoev che ha adattato il software su misura per ri­spon­de­re alle esigenze del motore di ricerca russo Rambler, ma allo stesso tempo viene anche uti­liz­za­to come web server, come reverse proxy e come e-mail proxy.

Nei prossimi paragrafi mettiamo a confronto i due web server e ap­pro­fon­dia­mo le loro dif­fe­ren­ze ar­chi­tet­tu­ra­li, la loro con­fi­gu­ra­zio­ne, le pos­si­bi­li­tà di esten­sio­ne, oltre che alla loro com­pa­ti­bi­li­tà, alla loro do­cu­men­ta­zio­ne e al supporto messo a di­spo­si­zio­ne.

Consiglio

Negli articoli di base su Apache e NGINX trovate un’in­tro­du­zio­ne generale a entrambi i web server open source messi a confronto, oltre che una guida sulla loro in­stal­la­zio­ne e con­fi­gu­ra­zio­ne.

Dif­fe­ren­ze ar­chi­tet­tu­ra­li

I web server Apache e NGINX si basano su ar­chi­tet­tu­re software com­ple­ta­men­te diverse. Alla base vi sono quindi diversi modelli di gestione della con­nes­sio­ne, dell’in­ter­pre­ta­zio­ne delle richieste client, dell’uso di contenuti web statici e dinamici, oltre che della con­fi­gu­ra­zio­ne.

Gestione della con­nes­sio­ne

Es­sen­zial­men­te i web server open source Apache e NGINX si dif­fe­ren­zia­no dal modo in cui trattano le richieste in entrata dei client (requests). Mentre alla base di Apache si trova un’ar­chi­tet­tu­ra basata sul processo (process-based), su NGINX la gestione delle con­nes­sio­ni si basa su un algoritmo di ela­bo­ra­zio­ne event-driven che consente di con­clu­de­re delle richieste ri­spar­mian­do risorse, anche se pro­ven­go­no da più con­nes­sio­ni con­tem­po­ra­nea­men­te. Ciò viene indicato come un grande vantaggio rispetto al server Apache HTTP, spe­cial­men­te dagli svi­lup­pa­to­ri NGINX. Ma anche il server Apache offre la pos­si­bi­li­tà di im­ple­men­ta­re gli eventi a partire dalla versione 2.4. Di seguito le dif­fe­ren­ze in dettaglio.

Il web server Apache segue un approccio in cui ogni richiesta client viene elaborata da un processo separato o thread. Nel caso di un unico thread (single threading), la modalità di fun­zio­na­men­to ori­gi­na­ria del server Apache HTTP, sorgono prima o poi dei problemi di blocco delle pe­ri­fe­ri­che I/O: i processi che ri­chie­do­no ope­ra­zio­ni di scrittura e di lettura vengono elaborati ri­go­ro­sa­men­te uno dietro l’altro. Una richiesta suc­ces­si­va rimane in coda di attesa fino a quando la pre­ce­den­te non ha ricevuto risposta. Si può aggirare tutto questo avviando con­tem­po­ra­nea­men­te più processi di single threading, una strategia che genera però un uso elevato delle risorse.

In al­ter­na­ti­va vengono uti­liz­za­ti i mec­ca­ni­smi di mul­ti­th­rea­ding. A dif­fe­ren­za del single threading dove in ogni processo è a di­spo­si­zio­ne un unico thread per ri­spon­de­re alle richieste del client, il mul­ti­th­rea­ding dà la pos­si­bi­li­tà di attivare più thread nello stesso processo. Visto che i thread su Linux, essendo dei processi, hanno bisogno di meno risorse, il mul­ti­th­rea­ding permette di com­pen­sa­re il grande fab­bi­so­gno di risorse dell’ar­chi­tet­tu­ra basata sui processi del server Apache.  

I mec­ca­ni­smi per l’ela­bo­ra­zio­ne parallela si possono integrare sulle richieste client su Apache tramite uno dei tre moduli multi-pro­ces­sing (MPM): mpm_prefork, mpm_worker, mpm_event.

  • mpm_prefork: il modulo Apache “Prefork“ offre una gestione del mul­ti­pro­ces­so sulla base di un mec­ca­ni­smo di single threading. Il modulo genera un processo padre che mette a di­spo­si­zio­ne una scorta di processi figli. In ogni processo figlio è attivo un thread che consente di ri­spon­de­re ri­spet­ti­va­men­te a una richiesta client. Fin quando sono presenti più processi single thread che arrivano come richieste client, le request vengono elaborate con­tem­po­ra­nea­men­te. Il numero dei processi di­spo­ni­bi­li di single threading viene definito con l’aiuto delle opzioni di con­fi­gu­ra­zio­ne server “Min­Spa­re­Ser­vers“ e “Ma­x­Spa­re­Ser­vers“. Prefork presenta gli svantaggi di per­for­man­ce nominati sopra in merito al single threading. È però van­tag­gio­sa l’in­di­pen­den­za completa di processi separati: se una con­nes­sio­ne viene persa per via di un processo errato, di solito non si riflette sulle con­nes­sio­ni che vengono elaborate in altri processi.
  • mpm_worker: con il modulo “Worker“, Apache mette a di­spo­si­zio­ne un mec­ca­ni­smo di mul­ti­th­rea­ding per l’ela­bo­ra­zio­ne parallela delle richieste client. Il numero dei thread che possono venire avviati per processo si può definire grazie all’opzione della con­fi­gu­ra­zio­ne del server “Th­read­sPer­Child”. Il modulo prevede un thread per ogni con­nes­sio­ne TCP. Fin quando sono a di­spo­si­zio­ne più thread che operano come richieste client, le request vengono portate a termine pa­ral­le­la­men­te. Il processo padre sorveglia sui thread non attivi (httpd).
    Gli utenti hanno a di­spo­si­zio­ne i comandi “Min­Spa­re­Th­reads“ e “Ma­x­Spa­re­Th­reads“ per definire da quale numero di thread non attivi vadano generati dei nuovi thread o debbano essere eliminati dalla memoria dei thread in funzione. Il modulo worker ha un fab­bi­so­gno di risorse es­sen­zial­men­te inferiore rispetto al modulo prefork. Visto che le con­nes­sio­ni non vengono elaborate in processi separati, un thread errato può avere ri­per­cus­sio­ni su tutto il processo di mul­ti­th­rea­ding e quindi su tutte le con­nes­sio­ni che vengono elaborate all’interno dello stesso. Inoltre worker, come prefork, è anche soggetto a so­vrac­ca­ri­chi tramite le co­sid­det­te con­nes­sio­ni keep alive (v. sotto).  
  • mpm_event: a partire dalla versione 2.4, il server HTTP Apache ha a di­spo­si­zio­ne “Event”, un terzo modulo di mul­ti­pro­ces­sing per la pro­dut­ti­vi­tà. Questo presenta una variante del modulo worker che si occupa di una di­stri­bu­zio­ne del carico tra i thread avviati. In aggiunta per ogni processo di mul­ti­th­rea­ding viene usato un co­sid­det­to listener thread che accoglie le richieste client in entrata e di­stri­bui­sce così i compiti correlati sui worker threads.
    Il modulo “Event” è stato svi­lup­pa­to per ot­ti­miz­za­re le con­nes­sio­ni keep alive, quindi le con­nes­sio­ni TCP, che vengono mantenute per con­sen­ti­re la tra­smis­sio­ne di altre richieste client o risposte server (responses). Se viene uti­liz­za­to il classico modulo worker, i worker threads man­ten­go­no so­li­ta­men­te le con­nes­sio­ni in­stau­ra­te e vengono così bloccate, anche quando non arrivano altre richieste. In caso di un numero elevato di con­nes­sio­ni keep alive è possibile che si verifichi un so­vrac­ca­ri­co del server. Invece il modulo event memorizza le con­nes­sio­ni keep alive nei listener thread in­di­pen­den­ti. I worker thread non vengono così bloccati e sono a di­spo­si­zio­ne per l’ela­bo­ra­zio­ne di altre richieste.

La seguente grafica indica una rap­pre­sen­ta­zio­ne sche­ma­ti­ca dell’ar­chi­tet­tu­ra basata su processi del web server Apache con utilizzo del modulo worker:

A seconda di quale modulo venga uti­liz­za­to, Apache risolve un problema di con­cor­ren­za, cioè la risposta con­tem­po­ra­nea di più richieste client, tramite processi ag­giun­ti­vi o thread. Entrambe le strategie di ri­so­lu­zio­ne vanno di pari passo con una maggiore domanda di risorse ag­giun­ti­ve, un fattore che diventa limitante nell’ambito del ri­di­men­sio­na­men­to del server Apache.

L’enorme richiesta di risorse dell’approccio di un processo per con­nes­sio­ne deriva dal fatto che per ogni processo ag­giun­ti­vo deve essere messo a di­spo­si­zio­ne un proprio ambiente di runtime. Ciò richiede l’as­se­gna­zio­ne del tempo di CPU e della memoria separata. Inoltre ogni modulo Apache, che deve essere messo a di­spo­si­zio­ne in un processo worker, viene caricato se­pa­ra­ta­men­te per ogni processo. Invece i thread si spar­ti­sco­no un ambiente di ese­cu­zio­ne (il programma) e lo spazio di in­di­riz­za­men­to nella memoria. L’overhead di thread ag­giun­ti­vi è così no­te­vol­men­te inferiore rispetto a quello dei processi. Ma anche il mul­ti­th­rea­ding richiede un’elevata capacità di calcolo, quando si tratta di com­mu­ta­zio­ne di contesto (context switch).

Come context switch si indica il processo in cui un sistema commuta da un processo o thread a un altro. Così il contesto del processo o thread concluso deve essere as­si­cu­ra­to e quello del nuovo deve essere generato o ri­pri­sti­na­to. Un processo am­mi­ni­stra­ti­vo im­pe­gna­ti­vo in cui devono essere caricati e salvati il registro CPU, le diverse tabelle e liste.

Il modulo mpm_event mette a di­spo­si­zio­ne un mec­ca­ni­smo event per il server Apache che salva l’ela­bo­ra­zio­ne delle con­nes­sio­ni in entrata in un listener thread. Questo consente di terminare le con­nes­sio­ni non più ne­ces­sa­rie (anche con­nes­sio­ni keep alive) e di ridurre così l’uso delle risorse. Non viene però risolto il problema del context switch che richiede molte risorse e che si verifica quando le richieste del listener thread vengono trasmesse alle con­nes­sio­ni mantenute da questo ai worker thread separati. 

Invece l’ar­chi­tet­tu­ra basata su eventi di NGINX realizza la con­cor­ren­za senza che sia ne­ces­sa­rio un processo o un thread ag­giun­ti­vo per ogni nuova con­nes­sio­ne. Un singolo processo NGINX può elaborare migliaia di con­nes­sio­ni HTTP con­tem­po­ra­nea­men­te. Questo viene rea­liz­za­to tramite un mec­ca­ni­smo di cicli, il co­sid­det­to event loop. Ciò consente di portare a termine le richieste client asin­cro­ni­ca­men­te all’interno di un thread.

Consiglio

Teo­ri­ca­men­te NGINX se la cava nell’ela­bo­ra­zio­ne delle con­nes­sio­ni solo con un processo di single threading. Per sfruttare in modo ottimale l’hardware, il web server viene di solito però avviato con un processo worker per ogni core del pro­ces­so­re (CPU) della macchina alla base.

A dif­fe­ren­za del web server Apache in cui si può de­li­mi­ta­re il numero dei processi attivi e dei thread solo tramite valori minimi e massimi, NGINX offre un modello di processo pre­ve­di­bi­le che viene regolato esat­ta­men­te sull’hardware a di­spo­si­zio­ne. Questo comprende un processo master, i processi di aiuto cache loader e cache manager, oltre che un numero di processi worker adattati al numero dei core del pro­ces­so­re e stabiliti con pre­ci­sio­ne at­tra­ver­so la con­fi­gu­ra­zio­ne.

  • Processo master: con il processo master si indica un processo so­vraor­di­na­to che esegue tutte le ope­ra­zio­ni basilari. Tra queste rientrano ad esempio l’in­se­ri­men­to della con­fi­gu­ra­zio­ne server, il col­le­ga­men­to della porta, oltre che la creazione di tutti gli altri tipi di processo seguenti.
  • Processi di aiuto: NGINX utilizza due processi di aiuto per la gestione della cache, cioè il cache loader e il cache manager.
    • Cache loader: il cache loader è re­spon­sa­bi­le del fatto che la cache basata sul disco fisso venga caricata nella RAM.
    • Cache manager: il compito del cache manager è di prestare at­ten­zio­ne al fatto che le voci della cache del disco fisso pre­sen­ti­no le di­men­sio­ni con­fi­gu­ra­te prima e le riducano quando ne­ces­sa­rio. Questo processo avviene pe­rio­di­ca­men­te.
  • Processo worker: i processi worker sono re­spon­sa­bi­li dell’ela­bo­ra­zio­ne delle con­nes­sio­ni, dei permessi di scrittura e di lettura sul disco fisso, oltre che della co­mu­ni­ca­zio­ne con i server upstream (server che mettono a di­spo­si­zio­ne servizi per gli altri server). Si tratta così degli unici processi del modello del processo NGINX che sono di soliti attivi.

La seguente grafica indica una rap­pre­sen­ta­zio­ne sche­ma­ti­ca del modello del processo NGINX:

Tutti i processi worker, avviati dal processo master NGINX durante la con­fi­gu­ra­zio­ne, si spar­ti­sco­no un set di listener socket (endpoint di co­mu­ni­ca­zio­ne). Al posto di avviare per ogni con­nes­sio­ne in entrata un proprio processo o thread, in ogni processo worker viene eseguito un event loop che consente l’ela­bo­ra­zio­ne asincrona di diverse migliaia di con­nes­sio­ni all’interno di un thread senza bloccare il processo. In più i processi worker ascoltano i listener socket con­ti­nua­men­te per rilevare gli eventi provocati dalle con­nes­sio­ni in entrata, le accolgono e durante la modifica delle richieste HTTP eseguono processi di scrittura e lettura nel socket.

Così NGINX non mette a di­spo­si­zio­ne nessun proprio mec­ca­ni­smo per la di­stri­bu­zio­ne delle con­nes­sio­ni sui processi worker. Al suo posto vengono uti­liz­za­te le funzioni kernel del sistema operativo. Gli schemi, che indicano come vanno elaborate le richieste in entrata, vengono messi a di­spo­si­zio­ne tramite macchine di stato separate (state machine) per HTTP, raw TCP, SMTP, IMAP e POP3.

In generale NGINX può essere indicato come un event handler che riceve in­for­ma­zio­ni sugli eventi dal kernel e dice al sistema operativo come si devono elaborare i compiti correlati. L’ela­bo­ra­zio­ne asincrona dei compiti all’interno degli event loop si basa su notifiche di eventi, funzioni di chiamata (callback) e timer. Questi mec­ca­ni­smi per­met­to­no a un processo worker di delegare un’ope­ra­zio­ne dopo l’altra al sistema operativo senza dover attendere pas­si­va­men­te il risultato di un’ope­ra­zio­ne o la risposta dei client. NGINX funge così da or­che­stra­to­re per il sistema operativo, che si fa carico della lettura e della scrittura di byte.

Questo tipo di gestione delle con­nes­sio­ni genera solo un overhead minimale per con­nes­sio­ni ag­giun­ti­ve. Tutto ciò che serve è un ulteriore File De­scrip­tor (FD) e un minimo di RAM ag­giun­ti­va nel processo worker. I context switch che ri­chie­do­no molte risorse, invece, sorgono solo quando non si ve­ri­fi­ca­no altri eventi all’interno di un event loop. Questa efficacia nell’ela­bo­ra­zio­ne delle richieste su in­nu­me­re­vo­li con­nes­sio­ni pre­de­sti­na NGINX a svolgere la funzione di load balancer per i siti molto fre­quen­ta­ti, come WordPress.com.

In sintesi

Con l’ar­chi­tet­tu­ra basata su eventi NGINX offre un’al­ter­na­ti­va alla gestione delle con­nes­sio­ni basata su processi del server Apache. Ma questa ca­rat­te­ri­sti­ca da sola non basta a dare una spie­ga­zio­ne del motivo per cui NGINX se la cavi così bene nei test di benchmark. Infatti anche Apache supporta un mec­ca­ni­smo di ela­bo­ra­zio­ne basato su eventi per le richieste client a partire dalla versione 2.4. Nel caso dei confronti di web server, come Apache vs. NGINX, prestate sempre at­ten­zio­ne con quali moduli il server web viene uti­liz­za­to nel test, come viene con­fi­gu­ra­to il web server e quali compiti deve compiere.

Come com­por­tar­si con i contenuti web statici e dinamici

Anche quando ha a che fare con contenuti web dinamici, NGINX segue un’altra strategia rispetto al server Apache.

Es­sen­zial­men­te vale il fatto che per poter con­se­gna­re i contenuti web dinamici, un web server deve ricorrere a un in­ter­pre­te che sia in grado di elaborare un lin­guag­gio di pro­gram­ma­zio­ne ne­ces­sa­rio come PHP, Perl, Python o Ruby. Apache mette perciò diversi moduli a di­spo­si­zio­ne, come mod_php, mod_perl, mod_python o mod_ruby, che con­sen­to­no di caricare il ri­spet­ti­vo in­ter­pre­te di­ret­ta­men­te nel web server. Così Apache stesso possiede la facoltà di elaborare i contenuti web dinamici che sono stati creati con il ri­spet­ti­vo lin­guag­gio di pro­gram­ma­zio­ne. Funzioni come la di­spo­ni­bi­li­tà di contenuti statici vengono già im­ple­men­ta­te con i moduli MPM nominati sopra.

Invece NGINX offre solo mec­ca­ni­smi per con­se­gna­re contenuti web statici. La messa a di­spo­si­zio­ne dei contenuti dinamici viene perciò im­ma­gaz­zi­na­ta sugli ap­pli­ca­tion server spe­cia­liz­za­ti al riguardo. NGINX funge in questo caso solo da proxy tra il client e l’upstream server. La co­mu­ni­ca­zio­ne avviene tramite pro­to­col­li come HTTP, FastCGI, SCGI, uWSGI e Memcached. Come possibili ap­pli­ca­tion server per la consegna di contenuti dinamici si prestano WebSphere, JBoss o Tomcat, ma anche il server Apache può essere uti­liz­za­to per questo scopo.

Entrambe le strategie nel trattare i contenuti dinamici e statici sono legati a vantaggi e svantaggi. Un modulo come mod_php consente al web server di eseguire da solo il codice PHP; non è ne­ces­sa­rio un ap­pli­ca­tion server separato. Ciò rende molto pratica l’am­mi­ni­stra­zio­ne delle pagine dinamiche. I moduli di in­ter­pre­te per i linguaggi di pro­gram­ma­zio­ne dinamici devono però essere caricati se­pa­ra­ta­men­te in ogni processo worker che concorre alla vi­sua­liz­za­zio­ne del contenuto. Nel caso di una grande quantità di processi worker ciò va di pari passo con un chiaro overhead che riduce NGINX, visto che l’in­ter­pre­te de­lo­ca­liz­za­to viene in­ter­pel­la­to solo se ne­ces­sa­rio.

Mentre NGINX dipende dall’in­te­ra­zio­ne con un in­ter­pre­te esterno, agli utenti Apache rimangono a di­spo­si­zio­ne entrambe le strategie. Anche Apache può essere applicato a un ap­pli­ca­tion server che si fa carico dell’in­ter­pre­ta­zio­ne di contenuti web dinamici. So­li­ta­men­te per questo viene uti­liz­za­to il pro­to­col­lo FastCGI e con il modulo mod_proxy_fcgi si può caricare una relativa in­ter­fac­cia.

In sintesi

Con entrambi i web server nel nostro confronto si possono vi­sua­liz­za­re pagine web dinamiche. Ma mentre il programma del codice Apache viene in­ter­pre­ta­to ed eseguito au­to­no­ma­men­te grazie a dei moduli, NGINX sposta questo passaggio su un ap­pli­ca­tion server esterno.

In­ter­pre­ta­zio­ne di richieste client

Per poter ri­spon­de­re ade­gua­ta­men­te ai programmi client (ad esempio browser o programmi di posta elet­tro­ni­ca), un server deve in­di­vi­dua­re, sulla base delle richieste, di quale risorsa necessita e dove si trova.

Il server Apache è stato concepito come web server, invece NGINX svolge sia funzioni da web server che da proxy server. Questa dif­fe­ren­za nel focus si riflette anche nel modo in cui il software in­ter­pre­ta le richieste client e assegna le risorse sul server.

N.B.

Anche il server Apache si può uti­liz­za­re come proxy server grazie all’aiuto del modulo mod_proxy.

I server Apache e NGINX di­spon­go­no entrambi di mec­ca­ni­smi che con­sen­to­no di in­ter­pre­ta­re le richieste in entrata sia come risorse fisiche nel file system sia come URI (Uniform Resource Iden­ti­fier). Mentre Apache lavora di default basandosi sui file, su NGINX occupa una posizione di primo piano l’ela­bo­ra­zio­ne delle richieste basata su URI. 

Se giunge una richiesta client al server Apache, questo parte re­go­lar­men­te dal pre­sup­po­sto che una precisa risorsa deve essere ri­chia­ma­ta dal file system del server. Visto che Apache offre la pos­si­bi­li­tà tramite Vir­tua­lHosts di mettere a di­spo­si­zio­ne diversi contenuti web sullo stesso server con nomi host, indirizzi IP e numeri di porta dif­fe­ren­ti, deve prima di tutto essere in­di­vi­dua­to a quale Vir­tua­lHo­st si riferisca la richiesta. Così il web server confronta il nome host, l’indirizzo IP e il numero di porta all’inizio della richiesta URI con i Vir­tua­lHosts definiti nel file prin­ci­pa­le di con­fi­gu­ra­zio­ne httpd.conf.

Il seguente codice di esempio indica una con­fi­gu­ra­zio­ne Apache in cui vengono gestiti entrambi i domini www.example.com e www.other-example.com con lo stesso indirizzo IP:

NameVirtualHost *:80
<VirtualHost *:80>
ServerName www.example.com
ServerAlias example.com *.example.com
DocumentRoot /data/www/example
</VirtualHost>
<VirtualHost *:80>
ServerName www.other-example.com
DocumentRoot /data/www/other-example
</VirtualHost>

L’asterisco (*) serve come se­gna­po­sto per un qualsiasi indirizzo IP. È Apache a decidere in quale Do­cu­men­tRoot (la cartella di partenza di un progetto web) viene ricercata la risorsa richiesta, con­fron­tan­do la direttiva Ser­ver­Na­me nel nome host contenuto nella richiesta.

Se Apache ha trovato il server de­si­de­ra­to, il request URI verrà ri­pro­dot­to di default sul file system del server (mapping). A questo scopo Apache utilizza il percorso contenuto nell’URI. In com­bi­na­zio­ne con la Do­cu­men­tRoot si ottiene il percorso per giungere alla risorsa.

In una richiesta con un request URI del tipo "http://www.example.org:80/public_html/images/logo.gif" Apache verrebbe ricercato (partendo dall’esempio esposto sopra) sotto al percorso seguente secondo la risorsa de­si­de­ra­ta:

/data/www/example/public_html/images/logo.gif
N.B.

Visto che 80 è la porta standard per il pro­to­col­lo HTTP, so­li­ta­men­te viene omessa.

Inoltre Apache confronta il request URI con blocchi di file e directory opzionali nella con­fi­gu­ra­zio­ne. Questi con­sen­to­no di definire delle direttive spe­ci­fi­che per le richieste che si ri­fe­ri­sco­no alle cartelle o ai file scelti (incluse le sot­to­car­tel­le).

Nel seguente esempio vengono definite delle direttive spe­ci­fi­che per la cartella public_html/images e il file private.html:

<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias example.com *.example.com
    DocumentRoot /data/www/example
      <Directory var/www/example.com/public_html/images>
          Order Allow,Deny
          Allow from all
     </Directory> 
      <Files public.html>
          Order Allow,Deny
          Deny from all
      </Files>
</VirtualHost>

Oltre a questo pro­ce­di­men­to standard, Apache nell’in­ter­pre­ta­zio­ne delle richieste client con la direttiva alias dà la pos­si­bi­li­tà di indicare una cartella al­ter­na­ti­va in cui ricercare la risorsa richiesta al posto che nella Do­cu­men­tRoot. Inoltre il server Apache mette a di­spo­si­zio­ne con mod_rewrite un modulo che consente agli utenti di ri­scri­ve­re gli URL o di inol­trar­li.

Consiglio

Trovate maggiori in­for­ma­zio­ni al riguardo nel nostro articolo sulle basi del Rewrite Engine.

Se Apache deve ri­chia­ma­re delle risorse che sono state create al di fuori del file system, viene usata la direttiva location che consente di definire le direttive per URI precisi.

Ma quello che è un’eccezione su Apache, su NGINX è un caso da manuale. NGINX analizza prima di tutto il request URI e lo confronta con i blocchi server e location nella con­fi­gu­ra­zio­ne del web server. Solo dopo si trova (se ne­ces­sa­rio) un mapping sul file system e la com­bi­na­zio­ne con la root (che cor­ri­spon­de alla Do­cu­men­tRoot del server Apache).

Grazie alla direttiva server NGINX individua quale host è re­spon­sa­bi­le per la risposta della richiesta client. Il blocco del server cor­ri­spon­de così a un Vir­tua­lHo­st nella con­fi­gu­ra­zio­ne Apache. In aggiunta il nome host, l’indirizzo IP e il numero di porta del Request URI vengono con­fron­ta­ti con tutti i blocchi server definiti nella con­fi­gu­ra­zio­ne del web server. Il seguente codice di esempio mostra tre blocchi server all’interno del file di con­fi­gu­ra­zio­ne NGINX nginx.conf:

server {
    listen 80;
    server_name example.org www.example.org;
    ...
}
server {
    listen 80;
    server_name example.net www.example.net;
    ...
}
server {
    listen 80;
    server_name example.com www.example.com;
    ...
}
N.B.

Di solito ogni blocco server comprende una serie di blocchi location. Nell’esempio attuale sono stati so­sti­tui­ti da un se­gna­po­sto (…).

Un confronto del request URI con i blocchi location all’interno di un blocco server avviene solo quando viene trovato il server richiesto. Così NGINX inserisce i blocchi location presenti e cerca la location che cor­ri­spon­de di più con quella del request URI. Ogni blocco location è co­sti­tui­to da direttive spe­ci­fi­che che indicano a NGINX come deve essere elaborata la richiesta cor­ri­spon­den­te.

Così le location possono essere definite di modo che vengano in­ter­pre­ta­te come prefisso per un percorso, come coin­ci­den­za esatta o espres­sio­ne regolare (Regular Ex­pres­sion, RegEx). Inoltre nella sintassi della con­fi­gu­ra­zio­ne server vengono uti­liz­za­ti i seguenti mo­di­fi­ca­to­ri:

Nessun mo­di­fi­ca­to­re La location viene in­ter­pre­ta­ta come prefisso. Tutte le richieste il cui URI presenta il prefisso definito nella direttiva location valgono come coin­ci­den­ti con la location. Se non si trova nessuna location più specifica, la richiesta verrà elaborata a seconda delle in­di­ca­zio­ni in questo blocco location.
= La location viene in­ter­pre­ta­ta come coin­ci­den­za esatta. Tutte le richieste il cui URI coincide esat­ta­men­te con la sequenza di caratteri pre­sen­ta­ta nella direttiva location, vengono elaborate secondo le in­di­ca­zio­ni contenute in questo blocco location.
 ~ La location viene in­ter­pre­ta­ta come espres­sio­ne regolare. Tutte le richieste il cui URI coincide con l’espres­sio­ne regolare vengono elaborate a seconda delle in­di­ca­zio­ni contenute in questo blocco location. Durante il confronto vengono prese in con­si­de­ra­zio­ne le scritte in maiuscolo e minuscolo (case-sensitive).
~* La location viene in­ter­pre­ta­ta come espres­sio­ne regolare. Tutte le richieste il cui URI coincide con l’espres­sio­ne regolare vengono elaborate a seconda delle in­di­ca­zio­ni contenute in questo blocco location. Durante il confronto non vengono prese in con­si­de­ra­zio­ne le scritte in maiuscolo e minuscolo (case-in­sen­si­ti­ve).

Nell’esempio seguente i tre blocchi location indicano il modo di ela­bo­ra­zio­ne delle richieste in entrata per i domini example.org e www.example.org:

server {
    listen 80;
    server_name example.org www.example.org;
    root /data/www;
    location / {
        index index.html index.php;
    }
    location ~* \.(gif|jpg|png)$ {
        expires 30d;
    }
location ~ \.php$ {
        fastcgi_pass localhost:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

Partendo da una richiesta client con il request URI "http://www.example.org:80/logo.gif",NGINX pro­ce­de­reb­be nel modo seguente per in­ter­pre­ta­re le richieste seguenti e far vi­sua­liz­za­re la risorsa de­si­de­ra­ta:

http://www.example.org:80/logo.gif
http://www.example.org:80/index.php

NGINX individua prima di tutto la location prefisso più specifica. Inoltre il web server inserisce tutte le location senza mo­di­fi­ca­to­re della serie e si ferma quando trova la prima location che coincide con la richiesta. Infine vengono inserite tutte le location che sono con­tras­se­gna­te con il mo­di­fi­ca­to­re RegEx (~­). Anche qui viene usato il primo match. Se non si trova nessuna location RegEx, il web server ricorre alla location prefisso in­di­vi­dua­ta pre­ce­den­te­men­te come fallback.

Il request URI www.example.org:80/logo.gif coincide ad esempio sia con la location prefisso / che con l’espres­sio­ne regolare \.(gif|jpg|png)$. NGINX ri­pro­dur­reb­be perciò la richiesta in com­bi­na­zio­ne con la root sul percorso di file /data/www/logo.gif e con­se­gne­reb­be la risorsa cor­ri­spon­den­te al client. L’head “expires” indica quando una risposta non è più da con­si­de­ra­re valida, ovvero nell’esempio attuale dopo 30 giorni: expires 30d.

Anche la richiesta della pagina PHP con l’URI www.example.org:80/index.php coincide con la location prefisso / oltre che con la location RegEx ~ \.php$, che viene trattata per prima. NGINX trasmette perciò la richiesta a un server FastCGI che ascolta su localhost:9000 ed è re­spon­sa­bi­le dell’ela­bo­ra­zio­ne dei contenuti dinamici. Così la direttiva fastcgi_param imposta il parametro FastCGI SCRIPT_FILENAME su /data/www/index.php. Infine il file viene eseguito sul server upstream. In questo modo la variabile $document_root cor­ri­spon­de alla direttiva root, la variabile $fastcgi_script_name a una parte dell’URI che segue sul nome host e il numero della porta: /index.php.

Questo pro­ce­di­men­to, uti­liz­za­to durante l’in­ter­pre­ta­zio­ne delle richieste client, risulta un po‘ com­pli­ca­to al primo sguardo e ciò è im­pu­ta­bi­le ai diversi campi di ap­pli­ca­zio­ne nei quali viene usato NGINX. Pa­ra­go­na­to al pro­ce­di­men­to primario basato sui file del server Apache HTTP, l’in­ter­pre­ta­zio­ne delle richieste basata su URI consente una maggiore fles­si­bi­li­tà nell’ela­bo­ra­zio­ne dei diversi schemi di richiesta. Ciò viene ad esempio richiesto quando NGINX non funge da web server, bensì da proxy server o da mail proxy server.

In sintesi

Apache viene uti­liz­za­to prima di tutto come web server e in­ter­pre­ta pri­ma­ria­men­te le richieste client basate sui file. Invece NGINX di solito lavora con URI e sottostà così anche ad altri schemi di richiesta.

Con­fi­gu­ra­zio­ne

Al contrario del server Apache, a NGINX si at­tri­bui­sce una maggiore velocità nella vi­sua­liz­za­zio­ne dei contenuti web statici, ri­con­du­ci­bi­le a dif­fe­ren­ze nella con­fi­gu­ra­zio­ne. Il web server Apache offre agli am­mi­ni­stra­to­ri la pos­si­bi­li­tà di una gestione sul livello delle cartelle, oltre che il file prin­ci­pa­le di con­fi­gu­ra­zio­ne httpd.conf. In aggiunta vengono uti­liz­za­ti i co­sid­det­ti file .htaccess. Questi file di con­fi­gu­ra­zio­ne de­cen­tra­liz­za­ti si possono prin­ci­pal­men­te im­ple­men­ta­re in qualsiasi cartella server. Le direttive che vengono definite in un .htaccess si ri­fe­ri­sco­no sia alla cartella che comprende il file di con­fi­gu­ra­zio­ne che alle relative sot­to­car­tel­le. In pratica vengono uti­liz­za­ti i file .htaccess per limitare l’accesso alla cartella a de­ter­mi­na­te cerchie di utenti, per pro­teg­ger­la con una password, oltre che per definire regole per la ricerca nelle cartelle, per mostrare gli avvisi di errori e impostare gli inoltri o la vi­sua­liz­za­zio­ne di contenuti al­ter­na­ti­vi. È ne­ces­sa­rio prestare at­ten­zio­ne al fatto che tutto questo si possa con­fi­gu­ra­re cen­tral­men­te nel file httpd.conf. Il file .htaccess diventa però rilevante nei modelli hosting come quelli di hosting condiviso dove l’accesso al file prin­ci­pa­le di con­fi­gu­ra­zio­ne è riservato al provider. La con­fi­gu­ra­zio­ne de­cen­tra­liz­za­ta tramite .htaccess consente agli utenti l’am­mi­ni­stra­zio­ne per i diversi ambiti del file system del server, ad esempio per le cartelle di progetto scelte, senza dargli accesso alla con­fi­gu­ra­zio­ne prin­ci­pa­le. Inoltre le modifiche vengono applicate sin da subito e senza dover riavviare il server. Invece NGINX offre solo la pos­si­bi­li­tà di con­fi­gu­ra­zio­ni centrali. Tutte le direttive vengono definite nel file nginx.conf. Con l’accesso a questo file un utente riceve il controllo sull’intero server. A dif­fe­ren­za di Apache, l’accesso am­mi­ni­stra­ti­vo non si può limitare alle cartelle se­le­zio­na­te. Da ciò ne derivano vantaggi e svantaggi. Infatti la con­fi­gu­ra­zio­ne centrale di NGINX è meno fles­si­bi­le rispetto a quella del server Apache, ma offre un so­stan­zia­le beneficio sul fronte della sicurezza: le modifiche alla con­fi­gu­ra­zio­ne del web server possono essere apportate solo dagli utenti che di­spon­go­no dei permessi di root. Ma più im­por­tan­te rispetto all’argomento sulla sicurezza è lo svan­tag­gio di per­for­man­ce di una con­fi­gu­ra­zio­ne de­cen­tra­ta tramite .htaccess. Già nella do­cu­men­ta­zio­ne del server Apache gli svi­lup­pa­to­ri con­si­glia­no di ri­nun­cia­re all’uso di .htaccess non appena è possibile l’accesso al file httpd.conf. Il motivo di ciò è la procedura che inserisce e in­ter­pre­ta i file di con­fi­gu­ra­zio­ne Apache. Come già scritto, Apache segue di default uno schema basato sui file per ri­spon­de­re alle richieste dei client. Visto che l’ar­chi­tet­tu­ra Apache consente una con­fi­gu­ra­zio­ne de­cen­tra­ta, il web server analizza il file .htaccess ri­cer­can­do la risorsa richiesta in ogni cartella lungo il percorso del file. Tutti i file di con­fi­gu­ra­zio­ne che at­tra­ver­sa vengono inseriti e in­ter­pre­ta­ti; questo schema rallenta no­te­vol­men­te il web server.

N.B.

In linea di principio gli am­mi­ni­stra­to­ri Apache sono lasciati liberi di scegliere se ricorrere a opzioni di con­fi­gu­ra­zio­ne de­cen­tra­liz­za­te del web server e se vogliono prendere in con­si­de­ra­zio­ne i relativi vantaggi e svantaggi. Nella do­cu­men­ta­zio­ne gli svi­lup­pa­to­ri mettono in risalto il fatto che tutte le con­fi­gu­ra­zio­ni .htaccess possono essere apportate per mezzo dei blocchi di directory anche nella con­fi­gu­ra­zio­ne prin­ci­pa­le httpd.conf.

Per questo gli utenti che vor­reb­be­ro di­sat­ti­va­re o limitare la con­fi­gu­ra­zio­ne de­cen­tra­liz­za­ta su Apache uti­liz­za­no la direttiva Al­lo­wO­ver­ri­de nei blocchi delle directory del file prin­ci­pa­le di con­fi­gu­ra­zio­ne httpd.conf e lo impostano su None. Ciò segnala al web server di ignorare tutti i file .htaccess nelle cartelle con­fi­gu­ra­te cor­ri­spon­den­te­men­te.

<VirtualHost *:80>
    ServerName example.com;
    ...
    DocumentRoot /data/www/example
      <Directory /data/www/example>
        AllowOverride None
        ...
      </Directory>
    ...
</VirtualHost>

Nello specifico la con­fi­gu­ra­zio­ne di esempio impone al web server di ignorare tutti i file .htaccess per l’host example.com.

In sintesi

A dif­fe­ren­za di NGINX che viene con­fi­gu­ra­to solo cen­tral­men­te, Apache offre con il file .htaccess la pos­si­bi­li­tà di impostare una con­fi­gu­ra­zio­ne de­cen­tra­ta e basata sulle cartelle. Se vengono uti­liz­za­ti i file .htaccess, il web server perde però velocità.

Pos­si­bi­li­tà di esten­sio­ni

Entrambi i web server del nostro confronto si basano su un sistema modulare grazie al quale il nucleo del software può essere ampliato con altri com­po­nen­ti ag­giun­ti­vi, se ne­ces­sa­rio. Ma fino alla versione 1.9.10 NGINX seguiva per la gestione dei moduli un’altra strategia es­sen­zia­le rispetto al prodotto con­cor­ren­te.

Il server Apache HTTP mette a di­spo­si­zio­ne due pos­si­bi­li­tà di ampliare il nucleo del software. I moduli si possono compilare durante lo sviluppo nei file binari di Apache o si possono caricare di­na­mi­ca­men­te e quindi durante il tempo di ese­cu­zio­ne.

Si possono di­stin­gue­re tre categorie di moduli Apache:

  • Moduli di base: i moduli di base di Apache com­pren­do­no tutti i com­po­nen­ti che mettono a di­spo­si­zio­ne le fun­zio­na­li­tà prin­ci­pa­li del web server.
  • Moduli di esten­sio­ne: queste esten­sio­ni sono dei moduli di Apache Foun­da­tion che vengono in­stal­la­ti come parte di Apache Di­stri­bu­tion. Nella do­cu­men­ta­zio­ne Apache in inglese si trova un riepilogo generale su tutti i moduli contenuti nell’in­stal­la­zio­ne standard di Apache 2.4.
  • Moduli di terze parti: questi moduli non vengono messi a di­spo­si­zio­ne dalla Apache Foun­da­tion, ma da altri fornitori esterni o da pro­gram­ma­to­ri autonomi.

Invece su NGINX la mo­du­la­ri­tà è da tempo limitata alle esten­sio­ni statiche che dovevano essere compilate nel file binario del nucleo del software. Proprio per gli utenti che non erano abituati a gestire alcuni com­po­nen­ti software senza il gestore di pacchetti della ri­spet­ti­va di­stri­bu­zio­ne, questo tipo di esten­sio­ne limitava no­te­vol­men­te la fles­si­bi­li­tà del web server. Il team di svi­lup­pa­to­ri ha mi­glio­ra­to questo punto: a partire dalla versione 1.9.11 (release del 09.02.2016), NGINX supporta mec­ca­ni­smi che con­sen­to­no di con­ver­ti­re moduli statici in dinamici, così che questi possano essere caricati durante il tempo di ese­cu­zio­ne tramite i file di con­fi­gu­ra­zio­ne. In entrambi i casi viene uti­liz­za­to il modulo API del server.

Tuttavia è ne­ces­sa­rio prestare at­ten­zio­ne al fatto che non tutti i moduli NGINX possono essere con­ver­ti­ti in moduli dinamici. Infatti i moduli che servono a mettere una patch al codice sorgente del server non do­vreb­be­ro essere caricati di­na­mi­ca­men­te. Inoltre NGINX limita nell’im­po­sta­zio­ne standard il numero di moduli dinamici che possono essere caricati con­tem­po­ra­nea­men­te a 128. Per aumentare questo valore limite, impostate la costante di NGX_MAX_DYNAMIC_MODULES nel codice sorgente di NGINX sul valore de­si­de­ra­to.

In aggiunta ai moduli ufficiali della do­cu­men­ta­zio­ne NGINX sono a di­spo­si­zio­ne degli utenti diversi moduli di terze parti.

Summary

Entrambi i web server si possono ampliare con moduli. Oltre ai moduli statici sono messi a di­spo­si­zio­ne quelli dinamici, che possono venire caricati nel programma in funzione, se ne­ces­sa­rio.

Do­cu­men­ta­zio­ne e supporto

Entrambi i progetti software sono ben do­cu­men­ta­ti e for­ni­sco­no in­for­ma­zio­ni di prima mano agli utenti grazie a wiki e blog.

Mentre la do­cu­men­ta­zio­ne di NGINX è di­spo­ni­bi­le solo in inglese e russo, il progetto Apache si con­trad­di­stin­gue per i suoi materiali in­for­ma­ti­vi in numerose lingue, anche se manca l’italiano. Inoltre è da notare che le guide non sono sempre ag­gior­na­te ed è quindi im­pre­scin­di­bi­le dare un’occhiata alla do­cu­men­ta­zio­ne in inglese anche in questo caso. Gli utenti ricevono aiuto in caso di problemi su entrambi i progetti open source dalla community. Così le mailing list fungono da forum di di­scus­sio­ne.

I piani di release tra­spa­ren­ti e le roadmap danno agli utenti la pos­si­bi­li­tà di in­stal­la­re gli sviluppi futuri. Gli errori software e le vul­ne­ra­bi­li­tà vengono re­gi­stra­te su entrambi i progetti in un report pubblico di bug e quindi elaborati.

In aggiunta al progetto open source NGINX Nginx, Inc. offre il prodotto com­mer­cia­le NGINX Plus. Pagando una quota d’uso annuale gli utenti si as­si­cu­ra­no delle funzioni ag­giun­ti­ve così come un supporto pro­fes­sio­na­le a carico del pro­dut­to­re. Sul sito di NGINX trovate una tabella di confronto di entrambi i prodotti. Non esiste un’edizione com­mer­cia­le del server Apache. I servizi di supporto a pagamento vengono offerti, invece, da diversi fornitori esterni.

In sintesi

Sia per il server Apache che per quello NGINX si trova una ricca do­cu­men­ta­zio­ne per un uso pro­fes­sio­na­le sui sistemi pro­dut­ti­vi.

Com­pa­ti­bi­li­tà ed eco­si­ste­ma

Il server Apache ca­rat­te­riz­za il World Wide Web da più di due decadi e per via delle sua quota di mercato rimane ancora lo standard per ec­cel­len­za per mettere a di­spo­si­zio­ne i contenuti web. Anche NGINX può guardare indietro a una storia di successi lunga 15 anni. Entrambi i web server si con­trad­di­stin­guo­no per un vasto supporto di diverse piat­ta­for­me. Mentre Apache è con­si­glia­to per tutti i sistemi operativi com­pa­ti­bi­li con Unix e Windows, la do­cu­men­ta­zio­ne NGINX indica che il web server è stato testato sui seguenti sistemi operativi: FreeBSD, Linux, Solaris, IBM AIX, HP-UX, macOS e Windows. Come server standard Apache emerge per un’estensiva com­pa­ti­bi­li­tà con i progetti di terze parti. Tutti gli standard web rilevanti si possono integrare tramite moduli. In più è da con­si­de­ra­re che la maggior parte delle persone in rete hanno di­me­sti­chez­za con Apache. Di solito gli am­mi­ni­stra­to­ri e gli svi­lup­pa­to­ri web impostano i loro primi progetti su piat­ta­for­me con­ve­nien­ti di hosting condiviso, che si basano a loro volta per la maggior parte su Apache e danno l’op­por­tu­ni­tà di una con­fi­gu­ra­zio­ne de­cen­tra­liz­za­ta tramite .htaccess. Inoltre il server Apache fa parte di diversi pacchetti di programmi open source per lo sviluppo ed è presente nei test software come XAMPP o AMPPS. Anche NGINX mette a di­spo­si­zio­ne degli utenti un grande eco­si­ste­ma di moduli. Inoltre il team degli svi­lup­pa­to­ri si occupa di in­trat­te­ne­re col­la­bo­ra­zio­ni con i diversi progetti software open source e pro­prie­ta­ri, oltre che con servizi di in­fra­strut­tu­ra come Amazon Web Services, Windows Azure e HP.

In sintesi

Entrambi i web server sono affermati. Gli utenti possono ricorrere a un grande eco­si­ste­ma. Apache ha il vantaggio, rispetto a NGINX, di aver incluso nel corso degli anni una grande community di utenti che si attiva per garantire le basi del web server. Tuttavia il fatto che migliaia di am­mi­ni­stra­to­ri abbiano con­trol­la­to e mi­glio­ra­to il codice sorgente del software non ga­ran­ti­sce la sicurezza del web server. Anche i nuovi utenti be­ne­fi­cia­no dell’enorme numero di am­mi­ni­stra­to­ri Apache esperti che aiutano la community in caso di problemi sul forum o tramite mailing list.

NGINX vs. Apache: dif­fe­ren­ze a confronto

Malgrado le grandi dif­fe­ren­ze nell’ar­chi­tet­tu­ra software, entrambi i web server offrono simili funzioni. Apache e NGINX vengono uti­liz­za­ti in scenari simili, ricorrono però a proprie strategie e modelli per ri­spon­de­re ai requisiti richiesti. La seguente tabella mette a confronto entrambi i progetti software con­si­de­ran­do­ne le ca­rat­te­ri­sti­che prin­ci­pa­li e indicando si­mi­li­tu­di­ni e di­ver­gen­ze.

Ca­rat­te­ri­sti­ca Apache NGINX
Funzione Web server Proxy server Web server Proxy server E-Mail proxy Load balancer
Lin­guag­gio di pro­gram­ma­zio­ne C C
Sistema operativo Tutte le piat­ta­for­me com­pa­ti­bi­li con Unix Windows FreeBSD Linux Solaris IBM AIX HP-UX macOS Windows
Data di rilascio 1995 2002
Licenza Apache License v2.0 Licenza BSD (Berkeley Software Di­stri­bu­tion)
Svi­lup­pa­to­re Apache Software Foun­da­tion Nginx, Inc.
Ar­chi­tet­tu­ra software Basato su processi/thread Basato su eventi/event-driven
Con­cor­ren­za Mul­ti­pro­ces­sing Mul­ti­th­rea­ding Event loop
Contenuti web statici
Contenuti web dinamici No
In­ter­pre­ta­zio­ne delle richieste client Prin­ci­pal­men­te basata su file Basata su URI
Con­fi­gu­ra­zio­ne Con­fi­gu­ra­zio­ne cen­tra­liz­za­ta tramite httpd.conf Con­fi­gu­ra­zio­ne de­cen­tra­liz­za­ta tramite.htaccess   Con­fi­gu­ra­zio­ne cen­tra­liz­za­ta tramite nginx.conf
Esten­sio­ni Moduli statici Moduli dinamici Moduli statici Moduli dinamici
Do­cu­men­ta­zio­ne Tedesco Inglese Danese Spagnolo Francese Giap­po­ne­se Coreano Por­to­ghe­se Turco Cinese Tedesco Inglese  
Supporto da parte dello svi­lup­pa­to­re No Sì (a pagamento su Nginx, Inc.)
Supporto della community Mailing list Wiki Mailing list Wiki

Con­clu­sio­ne

Con Apache e NGINX gli utenti hanno a di­spo­si­zio­ne due progetti open source stabili e sicuri. Nessuno dei due web server ne emerge però vincitore assoluto. Alla base di entrambi i progetti si trovano delle scelte di design es­sen­zial­men­te diverse che, a seconda di come viene uti­liz­za­to il software, implicano vantaggi e svantaggi.

Il server Apache HTTP offre un immenso re­per­to­rio di moduli che apre al software grazie a opzioni di con­fi­gu­ra­zio­ne fles­si­bi­li in­nu­me­re­vo­li campi di ap­pli­ca­zio­ne. Il web server rap­pre­sen­ta il software standard per scenari di hosting condiviso e in questo ambito si affermerà anche sui web server leggeri come NGINX. La pos­si­bi­li­tà di integrare degli in­ter­pre­ti di­ret­ta­men­te nel web server, tramite moduli per i linguaggi di pro­gram­ma­zio­ne come PHP, Perl, Python o Ruby, permette la consegna dei contenuti web dinamici senza dover ricorrere a un ap­pli­ca­tion server separato. Ciò rende il server Apache una soluzione pratica per siti piccoli e medio-grandi in cui i contenuti vengono generati di­na­mi­ca­men­te durante il suo utilizzo.

Al contrario NGINX non offre nessuna pos­si­bi­li­tà di elaborare i contenuti dinamici di per sé o di integrare degli in­ter­pre­ti cor­ri­spon­den­ti tramite moduli. Così è sempre ne­ces­sa­rio un ap­pli­ca­tion server separato, cosa che potrà sembrare uno sforzo inutile nel caso di siti piccoli e medio-grandi. Una struttura simile mostra però i suoi punti di forza in presenza di grandi progetti web e di un aumento del traffico.

So­li­ta­men­te NGINX viene uti­liz­za­to come load balancer per un gruppo di ap­pli­ca­tion server. Così il load balancer accoglie le richieste e decide a seconda del loro tipo se queste devono essere inoltrate a un server spe­cia­liz­za­to che opera in back­ground. I contenuti web statici vengono con­se­gna­ti di­ret­ta­men­te da NGINX. Invece, se un client richiede dei contenuti dinamici, il load balancer inoltra la richiesta a uno degli ap­pli­ca­tion server previsti per questo scopo. Questo server in­ter­pre­ta il lin­guag­gio di pro­gram­ma­zio­ne, riunisce i contenuti richiesti in una pagina web e li re­sti­tui­sce a un load balancer che si fa carico di nuovo della consegna al client. In questo modo si possono gestire ef­fi­ca­ce­men­te flussi di traffico elevati.

In più NGINX memorizza già i contenuti scaricati nella cache per un de­ter­mi­na­to periodo, di modo che i contenuti dinamici richiesti possano venire con­se­gna­ti di nuovo di­ret­ta­men­te dal load balancer senza che NGINX debba ricorrere nuo­va­men­te all’ap­pli­ca­tion server.

La de­lo­ca­liz­za­zio­ne dell’in­ter­pre­te su uno o più server back end separati ha il vantaggio che si riesce a scalare co­mo­da­men­te la serie di server, uti­liz­zan­do server back end ag­giun­ti­vi, se ne­ces­sa­rio, o potendo di­sat­ti­va­re i sistemi che non servono. In pratica molti utenti uti­liz­za­no una struttura di questo tipo, com­bi­nan­do NGINX e Apache e ap­pro­fit­tan­do così dei punti di forza di entrambi i web server.

Vai al menu prin­ci­pa­le