Torna al blog

Proxying HTTP, bilanciamento del carico, buffering e caching di Nginx: una panoramica

Proxying HTTP, bilanciamento del carico, buffering e caching di Nginx: una panoramica
Introduzione

Nginx è un server web ad alte prestazioni utilizzato anche come reverse proxy, mail proxy, load balancer e cache HTTP. Nginx è gratuito e open-source, consentendo a chiunque di scaricarlo e utilizzarlo nel proprio ambiente server.

Potresti aver già utilizzato Nginx per ospitare siti web. In questo tutorial parleremo delle altre funzionalità di Nginx. La funzionalità di proxy HTTP di Nginx le consente di inoltrare le richieste ai server HTTP di backend per l'elaborazione. Con questa funzionalità, è possibile configurare più server di backend. Ciò consente di scalare l'infrastruttura in base alle esigenze per gestire i picchi di richieste dei client.

Man mano che procederemo con il tutorial, imparerai a scalare la tua infrastruttura utilizzando le proprietà di bilanciamento del carico di Nginx, il buffering, e il caching delle risposte per migliorare le prestazioni del server e garantire un'esperienza migliore ai client. Cominciamo!

Prima di tutto, per iniziare con Nginx dai un'occhiata al nostro tutorial su come installare Nginx sul tuo server Ubuntu.

Informazioni generali sul proxying

Se la tua conoscenza dei server web si limita all'elaborazione delle richieste dei siti web e alla fornitura di pagine web, potresti chiederti perché abbiamo bisogno di fare il proxy delle richieste. Di seguito spiegheremo i motivi.

Un motivo per inoltrare le richieste ad altri server da Nginx è supportare la scalabilità della tua infrastruttura. Nginx gestisce per impostazione predefinita molte connessioni simultaneamente. Questo lo rende perfetto come primo punto di contatto per i client. Successivamente, può passare le richieste a vari server di backend per gestire l'effettiva elaborazione delle richieste dei client. Questo è ciò che distribuisce il carico. Di conseguenza, garantisce la possibilità di scalare l'infrastruttura il più possibile. Consente inoltre di spegnere altri server per manutenzione mentre gli altri continuano a servire le richieste.

Il secondo motivo per cui potresti voler inoltrare le richieste ad altri server è quando utilizzi server applicativi che non sono adatti a gestire direttamente le richieste dei client in ambienti di produzione reali. Diversi framework, inclusi alcuni server web, non sono adatti a prestazioni elevate come quelle di Nginx. Lasciare che Nginx sia il punto di ingresso e inoltri le richieste a questi server a basse prestazioni può garantire un'esperienza migliore ai tuoi utenti. Inoltre, può garantire una maggiore sicurezza per la tua applicazione.

Il processo di proxying delle richieste in Nginx comporta la manipolazione di una richiesta da parte del server Nginx e il suo passaggio ad altri server di backend per l'effettiva elaborazione. Una volta che gli altri server di backend hanno elaborato la richiesta, restituiscono il risultato a Nginx. Questo invia quindi il risultato come risposta al client. Il client in questo caso è un browser web o anche un'applicazione web mobile. Gli altri server di backend possono essere server locali non accessibili pubblicamente su Internet, server remoti o persino altri server virtuali all'interno delle configurazioni dei blocchi server di Nginx. Questi altri server a cui Nginx inoltra le richieste sono definiti server upstream.

Nginx può inoltrare richieste a server che comunicano utilizzando diversi protocolli, tra cui HTTP(S), Memcached, SCGI, FastCGI, e uWSGI. Per ogni tipo di protocollo esistono set di direttive. Il nostro focus per questo tutorial è il protocollo HTTP. Nginx analizza le richieste e i componenti del messaggio in un formato che il server upstream può interpretare ed elaborare.

Analisi di un proxy pass HTTP di base

Il tipo più semplice di proxy prevede il passaggio di una richiesta a un singolo server che comunica tramite HTTP. Questo tipo di proxy è generalmente noto come "proxy pass" ed è gestito dalla direttiva opportunamente denominata proxy_pass all'interno dei file di configurazione di Nginx.

La direttiva proxy_pass appare all'interno dei blocchi location. Si trova anche all'interno dei blocchi di un contesto location e nei contesti limit_except. Quando una richiesta corrisponde a una location con una direttiva proxy_pass all'interno, la richiesta va all'URL specificato dalla direttiva. Di seguito è riportato un esempio di frammento di configurazione:

proxy_pass_conf

Nell'esempio sopra, le richieste alla porta 80 andrebbero a localhost:3000:

nginx default page

Lo screenshot sopra mostra la pagina predefinita di Nginx quando si tenta di raggiungere localhost. Dopo aver riavviato il server Nginx con la direttiva proxy pass attiva, tutte le richieste andranno alla porta 3000. Un'applicazione demo è in esecuzione sulla porta 3000, come si può vedere dall'immagine qui sotto, ed è raggiungibile direttamente da localhost senza specificare la porta:

localhost after applying proy pass

Nel prossimo esempio, non è stato specificato alcun URI alla fine del server nella definizione di proxy_pass. Per le definizioni che rientrano in questo schema, l'URI richiesto dal client verrà passato al server a monte così com'è.

Ad esempio, quando questo blocco gestisce una richiesta per /match/url/here, l'URI della richiesta andrà al server example.com come http://example.com/match/url/here.

Di seguito è riportato un esempio di uno snippet di configurazione alternativo:

Come si può vedere nello snippet sopra, abbiamo definito un segmento URI alla fine del server proxy come new/url/prefix. Quando si definisce un URI nella definizione proxy_pass, la parte della richiesta che corrisponde alla definizione della location viene sostituita da questo URI quando va al server a monte per l'elaborazione.

Ad esempio, una richiesta per /match/url/here sul server Nginx passa al server a monte come http://example.com/new/url/here. /match/url viene sostituito da /new/url. Tieni a mente questo punto.

In alcuni casi, il passaggio degli URI come sopra non è possibile. In tali casi, Nginx ignora l'URI alla fine della definizione proxy_pass. In definitiva, al server a monte viene passato l'URI originale del client o l'URI modificato da altre direttive.

Un esempio è quando le espressioni regolari corrispondono alla location. Nginx potrebbe non essere in grado di determinare quale parte dell'URI corrisponda all'espressione. Di conseguenza, invia l'URI della richiesta originale del client. Ciò comporta la riscrittura e la gestione dell'URI del client nello stesso blocco. In tal caso, viene passato l'URI riscritto.

In che modo Nginx elabora gli header?

Gli header sono fondamentali per il modo in cui un server elabora una richiesta. Alcuni header possono includere informazioni di autenticazione. Pertanto, dobbiamo capire come il proxying di Nginx elaborerà gli header. La richiesta proxy da Nginx al server a monte apparirà diversa da quella proveniente direttamente dal client. Alcune delle differenze sono il risultato degli header che accompagnano la richiesta proxy.

Durante il proxying di una richiesta, Nginx apporterà delle modifiche agli header della richiesta che riceve dal client. Alcune di queste modifiche includono:

  • Eliminare tutti gli header vuoti. Gli header vuoti non fanno altro che gonfiare la richiesta, quindi non ha senso passarli al server a monte.

  • Tutti gli header contenenti trattini bassi sono considerati non validi per impostazione predefinita, quindi rimossi dalla richiesta. Se desideri modificare questo comportamento e consentire a Nginx di interpretare come validi gli header con i trattini bassi, puoi impostare la direttiva underscores_in_headers su "on". In caso contrario, tali header provenienti dal client non raggiungeranno mai il server a monte.

  • L'header "Host" viene riscritto con il valore specificato dalla variabile $proxy_host. Questo è l'indirizzo IP o il nome e il numero di porta del server a monte, come specificato dalla direttiva proxy_pass.

  • Il valore dell'header "Connection" cambia in "close". L'header di connessione contiene informazioni su una particolare connessione stabilita tra due parti. Quando Nginx imposta il suo valore su close, indica al server a monte che la connessione si chiuderà una volta data risposta alla richiesta originale, pertanto non deve aspettarsi che sia una connessione persistente.

Ecco alcuni punti che possiamo notare dalle modifiche agli header della richiesta proxy descritte sopra:

  • Se non desideri che un header venga passato al server a monte, impostarlo su una stringa vuota lo rimpiazzerà completamente rimuovendolo dalla richiesta.

  • Se l'applicazione nel server a monte elaborerà header non standard, assicurati che gli header non contengano un carattere di sottolineatura (underscore). Facoltativamente, puoi impostare la direttiva underscores_in_headers su “on” nella tua configurazione (valida sia nel contesto della dichiarazione del server predefinito per la combinazione indirizzo IP/porta sia nel contesto HTTP). In questo modo ti assicurerai che gli header non vengano contrassegnati come non validi e quindi vengano effettivamente passati al server a monte.

  • L'header “Host” è piuttosto importante nella maggior parte delle situazioni di proxying. Per impostazione predefinita è impostato sul valore di $proxy_host, una variabile contenente il nome di dominio o l'indirizzo IP e la porta recuperati dalla specifica proxy_pass. Questo indirizzo viene selezionato per impostazione predefinita ed estratto direttamente dalle informazioni di connessione. È l'unico indirizzo per il quale Nginx ha la garanzia che il server a monte risponderà.

Di seguito sono riportati i valori più comuni per l'header “Host”:

  • $host – una variabile impostata in ordine di preferenza sull'hostname della riga di richiesta stessa, sull'header “Host” della richiesta del client o sul nome del server corrispondente alla richiesta.

  • $http_host – una variabile che imposta l'header “Host” sull'header “Host” della richiesta del client. Gli header nella richiesta del client sono sempre disponibili per Nginx come variabili. Queste variabili iniziano con un prefisso $http_, seguito dal nome dell'header in lettere minuscole. Sebbene la variabile $http_host funzioni generalmente bene, quando la richiesta del client è priva di un header “Host” valido, ciò può causare il fallimento dell'inoltro.

  • $proxy_host – una variabile che imposta l'header “Host” sulla combinazione di nome di dominio o indirizzo IP e porta recuperata dalla specifica di proxy_pass. Questo è il comportamento predefinito, dal punto di vista di Nginx, e quindi considerato sicuro. Tuttavia, potrebbe non essere ciò di cui il server ha bisogno per gestire correttamente la richiesta.

La maggior parte delle configurazioni prevede l'impostazione dell'header “Host” sulla variabile $host. È altamente flessibile e fornirà header compilati accuratamente al server a monte.

Impostazione e modifica degli header

La direttiva proxy_set_header ci consente di impostare o modificare gli header per le connessioni proxy. Nell'header “Host” discusso in precedenza, possiamo fare quanto segue per modificare e aggiungere ulteriori header comuni con le richieste proxy:

Nel frammento di configurazione sopra riportato, impostiamo l'header “Host” sulla variabile $host che contiene informazioni sull'host originale richiesto. Impostiamo l'header X-Forwarded-Proto con le informazioni sullo schema della richiesta originale del client (può essere una richiesta HTTP o HTTPS).

Passiamo l'indirizzo IP effettivo del client a X-Real-IP. Ciò consente al server a monte di prendere decisioni appropriate o memorizzare i log in base all'IP di origine del client. L'header X-Forwarded-For contiene un elenco di tutti gli indirizzi IP appartenenti ai server attraverso i quali il client è stato veicolato tramite proxy prima di raggiungere questo punto. Nel frammento di codice sopra, lo impostiamo sulla variabile $proxy_add_x_forwarded_for. Questa variabile prenderà il valore dell'header X-Forwarded-For originale prelevato dal client e aggiungerà l'indirizzo IP del server proxy Nginx alla fine.

Se desideri che le direttive proxy_set_header vengano richiamate in più di una location, puoi spostarle nel contesto server o http. Considera il frammento di configurazione seguente:

Definire un contesto Upstream per il bilanciamento del carico delle connessioni proxy

Fino a questo punto, hai compreso come effettuare un semplice proxy HTTP verso un singolo server upstream di backend. Fortunatamente, con Nginx, puoi scalare tale configurazione definendo pool di server backend a cui inoltrare le richieste per la gestione.

Nginx fornisce una direttiva chiamata upstream che viene utilizzata per definire un pool di server. All'interno della configurazione della direttiva, devi specificare solo i server in grado di gestire la richiesta di un client. Nginx come server proxy consente di scalare l'infrastruttura con il minimo sforzo. La direttiva upstream deve essere specificata all'interno del contesto http della configurazione di Nginx.

Ecco un esempio che mostra la direttiva upstream:

Nel frammento di codice di configurazione sopra, abbiamo definito un contesto upstream chiamato several_backend_hosts. Il nome del contesto definito è ora disponibile all'interno dei proxy pass. Può essere utilizzato come se fosse un normale dominio, come mostrato nell'esempio. All'interno del blocco server, passiamo tutte le richieste effettuate a example.com/proxy-me/… al pool che abbiamo definito utilizzando la direttiva upstream, in questo caso, several_backend_hosts. Un host viene selezionato all'interno del pool per gestire le richieste in arrivo applicando un algoritmo configurabile. Per impostazione predefinita, la selezione segue un processo round-robin (circolare) – ogni richiesta viene instradata a un host diverso a turno.

Come modificare l'algoritmo di bilanciamento dell'upstream

Come evidenziato sopra, il processo di selezione segue un processo round-robin. In questa sezione vedremo come modificare l'algoritmo di bilanciamento utilizzato dal pool upstream. Per modificare l'algoritmo, si includono altre direttive o flag all'interno del contesto upstream come definito di seguito:

  • (round-robin) – se non viene specificata nessun'altra direttiva di bilanciamento upstream, per impostazione predefinita a ciascun server definito nel contesto upstream vengono passate le richieste in modo sequenziale a turno.

  • least_conn – questa direttiva indica all'upstream di selezionare il server backend con il minor numero di connessioni attive. Questo è applicabile in situazioni in cui le connessioni a un server backend possono persistere per un certo tempo.

  • hash – questa direttiva è comune per il proxying memcached. Le connessioni vengono passate ai server backend in base al valore di una chiave hash fornita in modo casuale. Il valore della chiave hash può essere costituito da variabili, testo o una combinazione di entrambi. hash risulta essere l'unico metodo di bilanciamento che richiede l'input degli utenti per fungere da chiave da utilizzare per l'hash.

  • ip_hash – questa direttiva indica all'upstream di distribuire le richieste a diversi server in base all'indirizzo IP del client. I primi tre ottetti dell'indirizzo IP sono la chiave per determinare quale server deve elaborare una richiesta. Un vantaggio di questa direttiva è che i client tendono a ricevere lo stesso server ogni volta, garantendo così la coerenza della sessione.

Ecco un esempio di come possiamo aggiungere la direttiva dell'algoritmo di bilanciamento al contesto upstream:

Nel frammento sopra, Nginx selezionerà uno qualsiasi dei server con il minor numero di connessioni per elaborare una richiesta in arrivo. La direttiva ip_hash segue la stessa sintassi. Per la direttiva hash, devi fornire una chiave a tua scelta su cui eseguire l'hashing, ecco un esempio:

L'hash utilizzato qui sarà il risultato dell’indirizzo IP e della porta del client. Il parametro opzionale consistent implementa l'algoritmo di hashing coerente ketama. Questo garantisce un impatto minimo sulla cache nel caso in cui si modifichino i server upstream.

Come specificare il peso del server per il bilanciamento

Per impostazione predefinita, quando si dichiarano i server backend, a ciascun server viene assegnato lo stesso peso. Si presuppone che ogni server disponga delle risorse e delle capacità per gestire la stessa quantità di carico, ovviamente tenendo conto dell'algoritmo di bilanciamento specificato nel contesto upstream. Per modificare questo comportamento predefinito, è possibile impostare un peso alternativo per ciascun server durante la dichiarazione. Consideriamo un esempio:

In questo esempio, host1.example.com riceverà il doppio del traffico rispetto agli altri due server. Il peso di ciascun server è impostato su uno per impostazione predefinita.

Liberare i server backend con i buffer

Durante la configurazione del proxy nella configurazione del server, potresti temere l'impatto sulle prestazioni dovuto all'aggiunta di altri server al processo. Fortunatamente, Nginx è dotato di funzionalità di buffering e caching che possono aiutare a mitigare questi problemi di prestazioni.

La velocità di due diverse connessioni influenzerà sicuramente l'esperienza del client durante il proxying verso un altro server:

  • La prima connessione è dal client al proxy Nginx.

  • La seconda connessione è dal proxy Nginx al server upstream di backend.

Nginx può regolare il suo comportamento per aiutare a ottimizzare l'una o l'altra connessione in base alle esigenze.

Se rimuoviamo i buffer, la trasmissione dei dati dal backend upstream al client inizia immediatamente sul proxy Nginx. Se sai che i tuoi client sono veloci, puoi disattivare completamente il buffering per garantire che i dati raggiungano il client abbastanza rapidamente. Quando il buffering è attivo, il proxy Nginx memorizza temporaneamente i dati di risposta ricevuti dal server upstream di backend. Successivamente, invia i dati al client a seconda della sua velocità. Una volta che Nginx ha la risposta nei suoi buffer, può chiudere la connessione con il server di backend. Distribuirà quindi i dati al client alla velocità supportata dal client stesso. Allo stesso tempo, consente al server di backend di continuare a elaborare altre richieste in arrivo.

Per impostazione predefinita, Nginx avrà il buffering attivo. Questo perché non possiamo conoscere la velocità di connessione dei client. I client tendono ad avere connessioni diverse che potrebbero essere più lente. Di seguito, definiremo le varie direttive che possiamo specificare per regolare il comportamento di buffering di Nginx. Le direttive possono essere definite nei contesti http, server o location, tuttavia, si noti che le direttive di dimensionamento sono configurate per richiesta. Pertanto, aumentarle oltre lo stretto necessario può influire sulle prestazioni del server in presenza di troppe richieste client in arrivo. Ecco le direttive:

  • proxy_buffering – la direttiva che controlla se il buffering è attivo per un particolare contesto e per i contesti figli. La configurazione predefinita per proxy_buffering è “on”.

  • proxy_buffer_size – la direttiva che specifica la dimensione del buffer per memorizzare gli header trovati in una risposta da un server backend. Gli header costituiscono la prima parte della risposta da un server backend. Il buffering di questi header è separato dal resto della risposta. Per impostazione predefinita, la dimensione impostata per questo buffer è la stessa di proxy_buffers. Tuttavia, se le informazioni dell'header sono limitate, è possibile impostare la dimensione su un valore inferiore.

  • proxy_buffers – la direttiva che controlla il numero (primo argomento) e la dimensione (secondo argomento) dei buffer per le risposte proxy. La configurazione predefinita specifica 8 buffer di dimensione pari a una pagina di memoria (4k o 8k). È possibile consentire il buffering di più informazioni aumentando il numero di buffer.

  • proxy_max_temp_file_size – la direttiva che specifica la dimensione massima, per richiesta, di un file temporaneo su disco. I file temporanei vengono creati quando la risposta dell'upstream è troppo grande per essere contenuta in un buffer.

  • proxy_busy_buffers_size – la direttiva che specifica la dimensione massima dei buffer che possono passare come “client-ready” e quindi occupati. Un client può leggere i dati da un solo buffer alla volta. Tuttavia, i buffer sono in una coda per essere inviati al client in lotti. È possibile specificare la dimensione dello spazio di buffer consentito in questo stato modificando questa direttiva.

  • proxy_temp_file_write_size – la direttiva che specifica la quantità di dati che Nginx scriverà nel file temporaneo in una sola volta quando la risposta dal server backend upstream è troppo grande per essere contenuta nei buffer configurati.

  • proxy_temp_path – la direttiva che specifica il percorso della posizione sul disco in cui Nginx deve memorizzare i file temporanei quando la risposta dal server backend upstream è troppo grande per essere contenuta nei buffer configurati.

Nginx è altamente personalizzabile e fornisce diverse direttive per ottimizzare il comportamento del buffering. Nella maggior parte dei casi, i valori predefiniti funzioneranno benissimo. Allo stesso tempo, è utile sapere che è possibile regolare alcuni di questi valori per la propria implementazione personalizzata. Principalmente si vorranno regolare le direttive proxy_buffers e proxy_buffer_size.

Di seguito è riportato un esempio che aumenta il numero di proxy buffer disponibili per ciascuna richiesta upstream. Ciò avviene riducendo al contempo la dimensione del buffer che memorizza gli header:

Vediamo come è possibile servire i dati più velocemente ai client veloci disattivando completamente il buffering. Se il client non è abbastanza veloce, Nginx utilizzerà automaticamente i buffer. Tuttavia, invierà prima i dati al client invece di attendere i pool di buffer. Questa configurazione comporta uno svantaggio: fa sì che la connessione al server upstream rimanga aperta per i client lenti finché il client non ha ricevuto tutti i dati della risposta. Se il buffering è impostato su “off”, verrà utilizzato solo il buffer definito dalla direttiva proxy_buffer_size. Ecco uno snippet che mostra come specificare la disattivazione del buffering:

  • Configurazione di un'infrastruttura ad alta disponibilità (HA) (Configurazione opzionale)

È possibile aggiungere un set ridondante di bilanciatori di carico alla configurazione del proxy Nginx, garantendo che sia più robusto e, di conseguenza, altamente disponibile. Una configurazione ad alta disponibilità (HA) è un'infrastruttura senza un singolo punto di vulnerabilità. I bilanciatori di carico fanno parte di questa configurazione. Con più di un bilanciatore di carico, è possibile prevenire potenziali tempi di inattività se un bilanciatore di carico si guasta o va offline per manutenzione.

Come implementare il caching del proxy Nginx per ridurre i tempi di risposta

Nella sezione precedente, abbiamo discusso di come utilizzare il buffering per liberare i server backend in modo che possano gestire più richieste. Nginx è dotato di un'altra funzionalità che ci consente di memorizzare nella cache i dati di risposta dal backend. Rimuove completamente la necessità di connettersi all'upstream per tutte le richieste in arrivo.

Implementazione di una cache proxy

La direttiva proxy_cache_path ci consente di configurare una cache specificando un'area sul disco da utilizzare per memorizzare i contenuti proxy. La direttiva proxy_cache_path viene definita nel contesto http.

Il frammento di codice di configurazione seguente è un esempio di come sia possibile implementare un sistema di caching:

In questo frammento di codice, abbiamo utilizzato la direttiva proxy_cache_path per definire una directory sul file system che conterrà la nostra cache. /var/lib/nginx/cache è la directory che abbiamo impostato in questo caso. Siete liberi di definire un percorso di directory a vostra scelta. Utilizzate i seguenti comandi per creare le directory scelte, con i permessi e la proprietà corretti:

Nel frammento di codice, il parametro levels= specifica l'organizzazione della cache. Nginx creerà una chiave di cache eseguendo l'hashing del valore di una chiave (specificata utilizzando la direttiva proxy_cache_key). I livelli che abbiamo specificato (1:2) indicano che verranno create una directory a carattere singolo (ovvero l'ultimo carattere del valore hash) con una sottodirectory a due caratteri (presa dai successivi due caratteri a partire dalla fine del valore hash). Nella maggior parte dei casi, questo non vi riguarderà. Tuttavia, è utile sapere come aiuta Nginx a trovare rapidamente i valori rilevanti.

Il parametro keys_zone= definisce il nome di una zona di cache, nel nostro caso l'abbiamo chiamata backendcache. Qui definiamo anche quanti metadati vogliamo memorizzare. In questo esempio, stiamo memorizzando 8 MB di chiavi. Nginx può memorizzare circa 8000 voci per ogni megabyte. Il parametro max_size specifica la dimensione massima dei dati effettivamente memorizzati nella cache, 50 MB per il nostro esempio.

Si noti anche la direttiva proxy_cache_key utilizzata. Questa direttiva specifica la chiave che useremo per memorizzare i valori memorizzati nella cache. Useremo la stessa chiave per verificare se la richiesta esiste all'interno della cache. Abbiamo specificato che tale chiave sia una combinazione dello schema (http o https), del metodo di richiesta HTTP e dell'host e dell'URI richiesti.

Inoltre, abbiamo utilizzato la direttiva proxy_cache_valid. Questa direttiva può essere specificata più volte per vari codici di stato. Ci consente di specificare per quanto tempo memorizzare i valori a seconda del codice di stato. Nel frammento di codice, abbiamo specificato 10 minuti per i codici di successo e 1 minuto per le risposte 404.

Poiché abbiamo configurato la zona di cache, il passo successivo consiste nel rendere effettiva la configurazione dicendo a Nginx quando utilizzare la cache. Di seguito è riportato un frammento di configurazione che mostra come implementare l'uso di questa cache:

Nella direttiva proxy_cache, abbiamo specificato che la zona di cache backendcache deve essere utilizzata per questo contesto. Se hai scelto un nome diverso nella configurazione della cache, questo è il punto in cui lo sostituirai. Per ogni voce valida, Nginx controllerà la cache prima di passare una richiesta al server upstream di backend.

Definiamo la direttiva proxy_cache_bypass per utilizzare la variabile $http_cache_control. Questa variabile indica al server se deve rispondere con una risposta memorizzata nella cache o con una versione fresca e non memorizzata nella cache della risorsa. L'impostazione corretta di questa direttiva consente a Nginx di gestire correttamente vari tipi di richieste in arrivo dai client.

Viene specificata anche un'intestazione aggiuntiva chiamata X-Proxy-Cache. Questa intestazione ha il valore della variabile $upstream_cache_status. Ci fornisce informazioni sul fatto che la richiesta abbia generato un successo di cache (cache hit), un mancato accesso alla cache (cache miss) o se la cache sia stata esplicitamente bypassata. Tali informazioni possono essere utili per il client e cruciali durante il debug delle applicazioni.

Punti importanti sulla memorizzazione nella cache dei risultati

Sebbene la memorizzazione nella cache migliori notevolmente le prestazioni del server proxy, è necessario tenere presente quanto segue quando si implementa la memorizzazione nella cache:

Qualsiasi dato relativo alle informazioni personali dell’utente non deve essere memorizzato nella cache, per evitare scenari in cui i dati di un utente siano visibili a un altro utente.

I server di backend dovrebbero tenere conto di tutti gli elementi dinamici del sito web. Abbiamo diverse intestazioni Cache-Control che possiamo specificare nella nostra risposta per scopi diversi. Discutiamone:

  • no-cache – specifica che il proxy deve verificare se i dati sono cambiati sul backend prima di servire una risposta. Questo è applicabile per dati dinamici e importanti. Un'intestazione di metadati con hash ETag viene controllata a ogni richiesta e se il backend restituisce lo stesso valore di hash, viene servito il valore precedente.

  • no-store – specifica di non memorizzare nella cache alcun dato ricevuto, quindi ogni richiesta andrà al server per ottenere dati freschi. Questo è il metodo più sicuro per i dati sensibili.

  • private – specifica che nessuno spazio di cache condiviso deve memorizzare i dati. È possibile utilizzare questa intestazione per specificare la memorizzazione nella cache nel browser dell'utente, ma anche per informare il server proxy di considerare i dati non validi per le richieste successive.

  • public – specifica una risposta pubblica e consente la memorizzazione nella cache in qualsiasi punto della connessione.

È possibile specificare per quanto tempo si desidera che la cache duri in secondi utilizzando l'intestazione max-age. Le varie intestazioni definite sopra possono aiutarti a implementare la memorizzazione nella cache mantenendo al sicuro i dati sensibili, freschi i dati dinamici e, soprattutto, migliorando le prestazioni del tuo server.

Se i tuoi server di backend eseguono server Nginx, puoi specificare all'interno dei blocchi server per quanto tempo una cache deve essere valida. Puoi farlo aggiungendo la direttiva expires alla configurazione come mostrato di seguito:

Il primo blocco consente la memorizzazione nella cache dei contenuti per 59 minuti, mentre le secondo blocco indica nessuna memorizzazione nella cache. Queste impostazioni si applicano alle opzioni delle intestazioni Cache-Control, ad esempio, “no-cache” per il secondo blocco.

È possibile utilizzare la direttiva add-header per impostare valori aggiuntivi:

Conclusione

In questo tutorial abbiamo appreso le potenti funzionalità di Nginx. Nginx è sia un server web che, soprattutto, un reverse proxy. Il design di Nginx lo rende in grado di gestire migliaia di connessioni simultanee. Questo lo rende perfetto per il bilanciamento del carico. Grazie al suo design, il proxying delle richieste verso altri server di backend per l'elaborazione è piuttosto semplice.

Con le conoscenze acquisite in questo tutorial, dovresti essere in grado di implementare proxy e bilanciatori di carico complessi, grazie alla flessibilità di Nginx.

Ecco alcune risorse che puoi trovare sul nostro blog che possono aiutarti a familiarizzare ulteriormente con Nginx:

Buon computing!

author

Pranay Kapgate

Autore · CloudSigma

Preslav Dobrev è un designer creativo presso CloudSigma, con un focus su un'identità aziendale coerente attraverso l'uso di canali di marketing tradizionali e innovativi. È abile nel fondere la visione artistica con il marketing strategico per creare narrazioni di brand di grande impatto.

Commenti

Ancora nessun commento. Scrivi il primo.