Apache vs Nginx
Introduzione
Apache e Nginx sono i due server web open source più comuni al mondo. Assieme, sono responsabili della gestione di oltre il 50% del traffico Internet. Entrambe le soluzioni sono in grado di gestire carichi di lavoro di vario tipo e operare con altri software per fornire uno stack web completo.
Mentre Apache e Nginx condividono molte qualità, non dovrebbero essere considerati come del tutto intercambiabili. Ognuno eccelle a modo suo ed è importante comprendere le situazioni in cui potrebbe essere necessario rivalutare quale web server scegliere. Questo articolo sarà dedicato alla discussione su come ciascun server sia più adatto in differenti impieghi.
Panoramica generale
Prima di immergersi nelle differenze tra Apache e Nginx, diamo un rapido sguardo alla storia di questi due progetti e alle loro caratteristiche generali.
Apache
L’ “Apache HTTP Server” è stato creato da Robert McCool nel 1995 ed è stato sviluppato sotto la direzione della Apache Software Foundation dal 1999. Dal momento che il server web HTTP è il progetto originale della fondazione ed è di gran lunga il loro più famoso software, viene spesso chiamato semplicemente “Apache”.
Il server web Apache è il server più popolare su internet fin dal 1996. A causa di questa popolarità, Apache gode di un’ottima documentazione e della completa integrazione con altri software.
Gli amministratori di sistema scelgono di frequente Apache per la sua flessibilità, potenza, e un ampio supporto. È estensibile attraverso un sistema di moduli caricabili dinamicamente e in grado di far funzionare un gran numero di linguaggi interpretati senza dover usare programmi esterni ad Apache stesso.
Nginx
Nel 2002, Igor Sysoev iniziò a lavorare su Nginx in risposta al problema C10K, che è stato una sfida per i server web nell’intraprendere la gestione di diecimila connessioni contemporanee come requisito per un web al passo con i tempi. La prima release pubblica è del 2004, ed ha raggiunto l’obiettivo affidandosi ad una architettura asincrona guidata dagli eventi (events-driven).
Fin dal suo debutto, Nginx ha visto crescere la sua popolarità grazie all’utilizzo minimo delle risorse e la sua capacità di scalare facilmente su un hardware minimale. Nginx eccelle nella gestione rapida dei contenuti statici ed è stato progettato per passare le richieste dinamiche ad altri software più adatti allo scopo.
Gli amministratori di sistema scelgono di frequente Nginx per la sua efficienza nel gestire le risorse e la sua reattività sotto carico. I sostenitori di Nginx sottolineano la sua propensione alle caratteristiche di base da server web e a quelle di server proxy.
Architettura della gestione delle connessioni
Una grande differenza tra Apache e Nginx è il modo vero e proprio in cui gestiscono le connessioni e il traffico. Questa è forse la differenza più significativa nel modo in cui rispondono alle diverse condizioni di traffico.
Apache
Apache fornisce una varietà di moduli multi-processo (Apache li chiama MPM) che indicano il modo in cui vengono gestite le richieste dei client. Fondamentalmente, ciò consente agli amministratori di sistema di cambiare facilmente l’architettura della gestione delle connessioni. Queste architetture sono:
- mpm_prefork: Per gestire la richiesta, questo modulo genera processi con un singolo thread. Ogni figlio può gestire una sola connessione alla volta. Finché il numero di richieste è inferiore al numero di processi, l’MPM è molto veloce. Tuttavia, le prestazioni degradano rapidamente quando le richieste superano il numero di processi, quindi in determinati contesti non è una buona scelta. Ogni processo ha un impatto significativo sul consumo di RAM, quindi l’MPM è difficile da scalare in maniera efficace. L’MPM può essere ancora una buona scelta se viene utilizzato in combinazione con altri componenti che non sono sono stati pensati per i thread. Ad esempio, il PHP non è thread-safe, quindi l’MPM è raccomandato quale unico modo sicuro di lavorare con mod_php, il modulo Apache per l’elaborazione dei file PHP.
- mpm_worker: Questo modulo genera processi che possono gestire più thread per ciascuno. Ognuno di questi thread può gestire una singola connessione. I thread sono molto più efficienti rispetto ai processi, il che significa che questo MPM scala meglio rispetto all’MPM prefork. Poiché ci sono più thread che processi, vuol dire anche che le nuove connessioni possono usare immediatamente un thread libero invece di dover attendere un processo libero.
- mpm_event: Nella maggior parte dei casi, questo modulo è simile al modulo worker, ma è ottimizzato per gestire connessioni keep-alive. Quando si utilizza l’MPM worker, una connessione mantiene un thread indipendentemente dal fatto che ci sia una connessione attiva. L’evento MPM gestisce connessioni keep-alive accantonando dei thread dedicati alla gestione delle connessioni keep-alive e facendo passare le richieste attive ad altri thread. Ciò fa sì che il modulo eviti di rimanere invischiato da richieste keep-alive, permettendo così un’esecuzione più veloce. È stato definito stabile con il rilascio di Apache 2.4.
Come si può vedere, Apache fornisce un’architettura flessibile nella scelta di diversi algoritmi di gestione delle connessioni e delle richieste. Le scelte sono principalmente una funzione dell’evoluzione del server e della crescente necessità di concorrenza, come è stato per l’intera internet.
Nginx
Nginx è salito alla ribalta dopo Apache, con una maggiore consapevolezza sui problemi di concorrenza che si trovano ad affrontare i siti scalabili. Sfruttando questa conoscenza, Nginx è stato progettato da zero ed utilizza un algoritmo asincrono, non-bloccante, di gestione delle connessioni in base agli eventi (event-driven).
Nginx genera processi worker, ognuno dei quali in è grado di gestire migliaia di connessioni. I processi worker fanno ciò implementando un veloce meccanismo di loop che verifica ed elabora continumanente gli eventi. Il disaccoppiamento dell’effettivo carico di lavoro dalle connessioni permette a ciascun worker di occuparsi di una connessione solo quando viene attivato un nuovo evento.
Ciascuna delle connessioni gestite dal worker viene posta all’interno del loop di eventi dove risiede con le altre connessioni. All’interno del ciclo, gli eventi vengono elaborati in modo asincrono, consentendo all’elaborazione di venire gestita in modo non bloccante. Quando la connessione viene chiusa, viene rimossa dal loop.
Questo stile di elaborazione delle connessioni consente a Nginx di scalare davvero tanto con risorse limitate. Dal momento che il server è single-threaded e i processi non vengono generati per gestire ogni nuova connessione, l’utilizzo della memoria e della CPU tende a rimanere relativamente costante, anche nei momenti di carico pesante.
Contenuto Statico vs Dinamico
In termini di casi d’uso reali, uno dei paragoni più comuni tra Apache e Nginx è il modo in cui ciascun server gestisce le richieste di contenuti statici e dinamici.
Apache
I server Apache sono in grado di gestire i contenuti statici utilizzando l’ordinaria modalità basata sui file. L’esecuzione di queste operazioni è principalmente compito dei metodi MPM sopra descritti.
Apache può elaborare anche contenuti dinamici grazie all’integrazione di un interprete del linguaggio che si vuole usare, in ciascuna delle sue istanze dei worker. Ciò permette di eseguire il contenuto dinamico nel web server stesso, senza dover ricorrere a componenti esterni. Questi interpreti possono essere attivati attraverso l’uso di moduli caricabili dinamicamente.
La capacità di Apache di gestire contenuti dinamici internamente implica che la configurazione dell’esecuzione di contenuti dimanici tende ad essere più semplice. La comunicazione non ha bisogno di essere coordinata con un software aggiuntivo ed i moduli possono essere scambiati facilmente nel caso in cui ci sia un cambiamento di ciò che necessita ai contenuti [per essere processati, NdT].
Nginx
Nginx non ha alcuna capacità di elaborare contenuti dinamici in modo nativo. Per gestire PHP ed altre richieste dal contenuto dinamico, Nginx è costretto a passare l’esecuzione ad un interprete esterno ed attendere di poter reinviare il contenuto elaborato. In tal caso il risultato può essere trasmesso al client.
Per gli amministratori di sistema, ciò significa dover configurare la comunicazione che intercorre tra Nginx e l’interprete attraverso uno dei protocolli che Nginx è in grado di gestire (http, FastCGI, SCGI, uWSGI, memcache). Ciò può complicare leggermente le cose, soprattutto quando si cerca di anticipare il numero di connessioni consentite, dato che verrà utilizzata un’ulteriore connessione per ogni chiamata all’interprete.
Tuttavia, anche questo metodo presenta alcuni vantaggi. Dal momento che l’interprete dinamico non è incorporato nel processo worker, l’overhead dato dall’interprete riguarderà il solo contenuto dinamico. Il contenuto statico può essere servito in un colpo solo e l’interprete sarà chiamato solo quando necessario. Anche Apache può funzionare in questo modo, ma così non si potranno avere i benefici visti nella sezione precedente.
Configurazione Distribuita VS Centralizzata
Per gli amministratori di sistema, una delle differenze che saltano più facilmente all’occhio tra questi due software è se sia consentita o meno una configurazione a livello di directory all’interno delle directory stesse.
Apache
Apache include un’opzione che consente l’uso di configurazioni aggiuntive basate sulle directory. Ciò avviene controllando e intepretando le direttive poste in file nascosti all’interno delle directory stesse. Questi file sono noti come file .htaccess .
Dal momento che questi file risiedono all’interno delle directory stesse, durante la gestione di una richiesta Apache controlla la presenza di un file .htaccess in ogni parte del path del file richiesto e applica le direttive che trova al suo interno. Ciò permette una configurazione decentrata efficace del server web, che viene spesso utilizzata per implementare l’URL rewrite, le restrizioni di accesso, l’autorizzazione e l’autenticazione, ed anche le politiche di caching.
Mentre gli esempi di cui sopra possono essere configurati nel file di configurazione principale di Apache, i file .htaccess hanno alcuni vantaggi importanti. Innanzitutto, poiché i file vengono interpretati ogni volta che vengono trovati in un path della richiesta, il loro scopo trova subito compimento, senza dover far ripartire il server. In secondo luogo rende possibile consentire agli utenti non privilegiati il controllo di alcuni aspetti dei loro contenuti web senza dar loro il controllo sull’intero file di configurazione.
Questo, per alcuni software web come i sistemi di gestione dei contenuti, facilita la configurazione del proprio ambiente senza dover fornire l’accesso al file di configurazione centrale. Ciò viene usato anche dai fornitori di shared hosting per mantenere il controllo della configurazione principale dando allo stesso tempo ai clienti il controllo sulle proprie specifiche directory.
Nginx
Nginx non interpreta file .htaccess né fornisce alcun meccanismo per valutare una configurazione per directory al di fuori del file di configurazione principale. Ciò può essere meno flessibile rispetto al modello di Apache, ma ha i suoi vantaggi.
Il miglioramento più importane rispetto al sistema di configurazione a livello di directory offerto da .htaccess, è l’aumento delle prestazioni. Per una tipica configurazione di Apache che può consentire un .htaccess in ogni directory, il server verifica la presenza di questi file in ognuna delle directory genitore che portano al file richiesto, per ogni richiesta. Se in questa ricerca vengono trovati uno o più file .htaccess, devono essere letti e interpretati. Non permettendo l’override delle directory, Nginx può servire richieste più velocemente facendo una sola ricerca della directory e una sola lettura di file per ogni richiesta (assumendo che il file si trovi nella struttura convenzionale della directory).
Un altro vantaggio è legato alla sicurezza. Distribuire l’accesso alle configurazioni a livello di directory distribuisce anche la responsabilità della sicurezza ai singoli utenti, sui quali non si dovrebbe far affidamento per una corretta gestione di questo compito. La garanzia che l’amministratore mangenga il controllo sull’intero web server è in grado di prevenire alcuni passi falsi riguardanti la sicurezza che possono verificarsi quando l’accesso è dato a terzi.
Se queste preoccupazioni vi saltano all’orecchio, tenete a mente che in Apache è possibile disattivare l’interpretazione degli .htaccess.
Interpretazione basata sui file vs interpretazione basata su URI
Un’altra area nella quale i due server differiscono è il modo in cui il server web interpreta le richieste e le associa alle effettive risorse del sistema.
Apache
Apache ha la capacità di interpretare una richiesta come una risorsa fisica sul filesystem o come un URI che necessita di una valutazione più astratta. In generale, nel primo caso Apache utilizza i blocchi <Directory> o <Files>, nel caso di risorse più astratte utilizza i blocchi <Location>.
Dato che Apache è il risultato di una progettazione di un web server da zero, il comportamento predefinito è di solito quello di interpretare le richieste come risorse del file system. Si inizia prendendo la directory root del documento, aggiungendo la parte della richiesta seguita dal numero di host e dalla porta per cercare di trovare un file vero e proprio. In sostanza, la gerarchia del filesystem è rappresentata sul web come l’albero dei documenti raggiungibili.
Apache fornisce una serie di alternative per i casi in cui la richiesta non trova corrispondenza al filesystem sottostante. Per esempio, una direttiva Alias può essere utilizzata per mappare ad una posizione alternativa. Usare i blocchi <Location> è un metodo per lavorare con l’URI stesso anziché con il filesystem. Ci sono anche varianti con le espressioni regolari che possono essere utilizzate per usare la configurazione sul filesystem in maniera più flessibile.
Sebbene Apache sia in grado di operare sia sul filesystem sottostante sia sullo spazio web, fa pesantemente affidamento alle funzioni del filesystem. Ce ne si può rendere conto in alcune delle decisioni nella progettazione, compreso l’uso dei file .htaccess per la configurazione a directory. Nei casi in cui la richiesta rispecchia il filesystem sottostante, è la stessa documentazione Apache (Apache Docs) a diffidare dall’utilizzo dei blocchi basati sugli URI per la limitazione dell’accesso.
Nginx
Nginx è stato creato per essere sia un server web che un server proxy. A causa dell’architettura richiesta per questi due ruoli, Nginx lavora principalmente con gli URI, facendone la trasposizione al file system quando necessario.
Ce ne si può rendere conto in certi modi in cui i file di configurazione di Nginx sono costruiti ed interpretati. Nginx non prevede un meccanismo per specificare la configurazione di una directory del filesystem, analizza invece l’URI stesso.
Ad esempio, i blocchi di configurazione principali per Nginx sono i blocchi server e location. Il blocco server interpreta l’host richiesto, mentre i blocchi location sono responsabili della ricerca di una corrispondenza con porzioni di URI che stanno dopo l’host e la porta. A questo punto, la richiesta viene interpretata come un URI e non come una posizione nel filesystem.
Per i file statici, tutte le richieste alla fine devono essere mappate su un percorso nel filesystem. In primo luogo, Nginx seleziona i blocchi server e location che gestiranno la richiesta e quindi unisce la directory root del documento con l’URI, adattando tutto ciò che è necessario in base alla configurazione specificata.
Ciò potrà sembrare dello stesso tipo [di quella di Apache, NdT], ma fare come prima cosa il parsing delle richieste come URI invece che come posizioni nel filesystem, consente a Nginx di operare più facilmente in ambedue i ruori di server web/mail e di server proxy. Nginx viene configurato impostando semplicemente il modo di rispondere a diversi pattern di richiesta. Nginx non controlla il filesystem fino a quando non è pronto a servire la richiesta, il che spiega il motivo per cui non utilizza un formato tipo i file .htaccess.
Moduli
Sia Nginx che Apache sono espandibili attraverso dei sistemi a moduli , ma il modo in cui operano differisce in modo significativo.
Apache
Il sistema modulare di Apache permette di caricare o scaricare moduli in modo dinamico in modo da soddisfare ogni esigenza nel corso dell’esecuzione del server. Il nucleo di Apache è sempre presente, mentre i moduli possono essere attivati o disattivati, aggiungendo o rimuovendo funzionalità aggiuntive e hook [tecnica di codifica di un programma che permette all’utente di estenderlo, NdT] al server principale.
Apache utilizza questa funzionalità per una grande varietà di compiti. Grazie alla maturità della piattaforma, vi è una vasta disponibilità di moduli. Questi moduli possono essere utilizzati per modificare alcune delle funzionalità di base del server, per esempio mod_php che incorpora un interprete PHP in ciascun worker in esecuzione.
I moduli però non sono limitati al trattamento dei contenuti dinamici. Tra le altre funzioni, i moduli possono essere utilizzati per la riscrittura degli URL, l’autenticazione dei client, l’hardening del server, il log, il caching, la compressione, le funzioni di proxy, la limitazione della banda e la cifratura. I moduli dinamici possono estendere le funzionalità di base in modo significativo senza richiedere troppo lavoro extra.
Nginx
Anche Nginx implementa un sistema modulare, ma è piuttosto diverso dal sistema Apache. In Nginx, i moduli non sono caricabili dinamicamente, quindi devono essere scelti e compilati nel programma principale.
Per molti utenti, ciò rende Nginx molto meno flessibile. Questo è vero soprattutto per gli utenti a cui non piace mantenere le proprie versioni dei programmi compilati al di fuori del tradizionale sistema di gestione dei pacchetti della distribuzione. Mentre i pacchetti delle distribuzioni tendono ad includere i moduli più comuni, se si ha bisogno di un modulo non standard si dovrà compilare da sé il server dai sorgenti.
I moduli Nginx sono tuttavia molto utili e permettono di far fare al server ciò che si desidera semplicemente includendo la funzionalità che si intende utilizzare. Qualche utente potrebbe anche considere tutto ciò più sicuro, visto che non si possono far caricare al server delle componenti arbitrarie. Tuttavia, se il server viene sempre lasciato in una modalità in cui questo è possibile, è probabile che sia già compromesso.
I moduli Nginx permettono molte delle stesse funzionalità dei moduli di Apache. Ad esempio, i moduli Nginx sono in grado di fornire il supporto proxy, la compressione, la limitazione di banda, il logging, la riscrittura, la geolocalizzazione, l’autenticazione, la crittografia, lo streaming e le funzionalità di posta elettronica.
Supporto, Compatibilità, Ecosistema e Documentazione
Un punto importante da considerare è che il vero modo per rendere un sistema funzionante sarà dato dall’offerta di assistenza e supporto disponibile con altri software.
Apache
Visto che Apache è stato popolare per così tanto tempo, il supporto per il server è discretamente onnipresente. È disponibile una grande quantità di documentazione ufficiale e di terze parti per il server principale e per i casi che coinvolgono Apache con altri software.
Assieme alla documentazione, molti strumenti e progetti web includono strumenti che permettono a questi strumenti e progetti stessi, il bootstrap all’interno di un ambiente di Apache. Questo ambiente può essere incluso nei progetti stessi, o nei pacchetti manutenuti dalle persone che si occupano dei pacchetti della vostra distribuzione.
Apache, in generale, troverà maggiore supporto in progetti di terze parti semplicemente per la sua quota di mercato e per il periodo di tempo da cui è disponibile. Gli amministratori di sistema hanno una più alta probabilità di avere pratica con Apache, non solo a causa della sua diffusione, ma anche perché molte persone cominciano con lo shared hosting che si basa quasi esclusivamente su Apache a causa delle capacità di gestione distribuita, possibili grazie ad .htaccess .
Nginx
Nginx sta avendo un supporto crescente visto che sempre più utenti lo adottano per la sua attitudine alle prestazioni pure, ma ha ancora un po’ di ritardo da recuperare in alcuni settori chiave.
In passato era difficile trovare della documentazione completa riguardante Nginx in lingua ingles , perché la maggior parte dello sviluppo iniziale e la documentazione erano in russo. Dal momento che l’interesse per il progetto è cresciuto, la documentazione è stata completata e ora ci sono un sacco di risorse sulla gestione di Nginx sul sito ufficiale e non.
Per quanto riguarda le applicazioni di terze parti, il supporto e la documentazione stanno diventando disponibili con sempre più facilità e i manutentori dei pacchetti stanno cominciando, in alcuni casi, a fornire la scelta tra la configurazione automatica per Apache e quella per Nginx. Anche senza supporto, la configurazione di Nginx per poter funzionare con software alternativo è di solito chiara, a condizione che il progetto stesso documenti le sue esigenze (permessi, header, ecc.).
Uso combinato di Apache e Nginx
Andando oltre i vantaggi e i limiti sia di Apache che di Nginx , si può avere un’idea migliore di quale server sia più adatto alle vostre esigenze. Tuttavia, molti utenti trovano fattibile sfruttare i punti di forza di ciascun server usandoli assieme.
La tipica configurazione usata per ottenere questa collaborazione è quella di mettere Nginx a precedere Apache come proxy inverso. Ciò permetterà a Nginx di gestire tutte le richieste da parte dei client. Questo sfrutta la rapida velocità di elaborazione di Nginx e la sua capacità di gestire un gran numero di connessioni contemporaneamente.
Per i contenuti statici, nei quali Nginx eccelle, i file saranno serviti velocemente e direttamente al client. Per i contenuti dinamici, per esempio i file PHP, Nginx delegherà la richiesta ad Apache, che può così elaborare i risultati e restituire la pagina elaborata. Nginx può quindi passare il contenuto al client.
Questa configurazione funziona bene per molte persone, perché permette a Nginx di funzionare come una macchina di smistamento. Essa si occuperà di tutte le richieste che potrà e lascerà passare quelle che non riesce a servire nativamente. Riducendo le richieste che il server Apache è chiamato a gestire, siamo in grado di attenuare alcuni dei blocchi che si verificano quando un processo o un thread di Apache è occupato.
Questa configurazione permette anche di scalare, tramite l’aggiunta di server di backend aggiuntivi quando ve ne sarà bisogno. Nginx può essere configurato per migrare facilmente su un gruppo di server, aumentando la resilienza al fallimento e le prestazioni di questa configurazione.
Conclusioni
Come si può vedere, sia Apache che Nginx sono potenti, flessibili e fanno quello che devono. La decisione su quale server sia per voi il migliore si deve in gran parte alla valutazione delle vostre specifiche esigenze e dai test effettuati con i modelli che ci si aspetta di ottenere.
Ci sono differenze tra i progetti che hanno un impatto davvero importante sulle prestazioni vere e proprie, quelli sulle capacità, e quelli sul tempo di implementazione necessari per ottenere ciascuna soluzione funzionante. Tuttavia, queste soluzioni sono di solito il risultato di una serie di compromessi che non dovrebbero essere scartati con noncuranza. Alla fine, non ci sono web server che vanno bene per tutto, dunque usate la soluzione che meglio si adatta ai i vostri obiettivi.