Torna al blog

Algoritmi di selezione dei blocchi Server e Location di Nginx: Panoramica

Algoritmi di selezione dei blocchi Server e Location di Nginx: Panoramica

Introduzione

Nginx è tra le opzioni di server web più popolari al mondo. È in grado di gestire con successo una moltitudine di connessioni client simultanee. Allo stesso tempo, funziona come server di posta, web o proxy inverso.

Questa guida mira a delineare i metodi dietro le quinte che dirigono il modo in cui Nginx elabora le richieste dei client. Demistificheremo la progettazione dei blocchi server e location, oltre a spiegare come ridurre al meglio l'apparente imprevedibilità della gestione delle richieste.

Come prima cosa, ecco un tutorial completo su come installare Nginx sul tuo server Ubuntu. Ora iniziamo!

Configurazione dei blocchi con Nginx

L'approccio logico di Nginx prevede l'ordinamento delle configurazioni destinate a scopi diversi in blocchi di contenuto separati e più logici. Questi risiederanno in una struttura gerarchica. Quando un client effettua una richiesta, Nginx avvia un processo attraverso il quale determina quali di questi blocchi di configurazione siano i più applicabili per gestire tale richiesta. Ci concentreremo su questo processo decisionale.

I blocchi principali di cui parleremo saranno i blocchi server e i blocchi location blocchi. I server block sono un sottoinsieme delle configurazioni stabilite da Nginx che definiscono quale server virtuale sarà responsabile della gestione di un tipo definito di richiesta. Sono comunemente basati sull'indirizzo IP, sul nome di dominio o sulla porta della richiesta in arrivo. Gli amministratori configurano molteplici server block. Quindi, devono decidere quale delle connessioni debba gestire la richiesta.

I blocchi location risiedono all'interno dei blocchi server. Questi sono gli elementi decisionali su come e quali risorse è possibile sfruttare per gestire le richieste in arrivo al loro specifico server principale. Questo modello è altamente flessibile. Lo spazio URI può essere configurato per utilizzare questi blocchi nel modo che l'amministratore ritiene migliore.

Decidi quale blocco gestirà quale richiesta con Nginx

Nginx consente la definizione di più blocchi server. Tutti funzionano come server web virtuali diversi. Pertanto, è necessario un metodo che delinei quale server gestirà particolari richieste in arrivo. Questo viene fatto trovando la migliore corrispondenza per l'elaborazione della richiesta attraverso un sistema di controlli definiti.

Nginx gestisce principalmente due direttive principali dei blocchi server: listen e server_name.

Trova possibili corrispondenze con la direttiva 'Listen'

La prima cosa che Nginx valuta è la porta e l'indirizzo IP della richiesta. Successivamente, li confronta con la direttiva listen di ciascun server. Questo parsing dell'elenco dei server aiuta a isolare solo quei blocchi server che possono risolvere la richiesta in questione.

In genere, la direttiva listen definirà la porta e l'indirizzo IP a cui un particolare blocco server sarà responsabile di rispondere. Un blocco server che non presenta una direttiva listen riceve per impostazione predefinita i parametri di listen di 0.0.0.0:80. Se Nginx viene eseguito da un utente normale, non root, il parametro listen viene definito come 0.0.0.0:8080. Ciò significa che, qualunque sia l'interfaccia, se i blocchi provengono dalla porta 80, i blocchi definiti in questo modo risponderanno ad essi. Tuttavia, questo valore predefinito non ha un peso rilevante nel processo di selezione di un server.

È possibile configurare la direttiva listen per:

  • Un singolo indirizzo IP che ascolta le richieste sulla porta predefinita (80).
  • Una singola porta che ascolta su qualsiasi interfaccia su quella porta.
  • Una combinazione di porta e indirizzo IP.
  • Un percorso socket Unix impostato (questa opzione ha implicazioni solo quando le richieste passano attraverso server diversi).

Nginx implementerà un insieme di regole nel decidere a quale blocco server verrà inviata una richiesta. Le regole dipendono dalla particolare configurazione della direttiva listen. Esse sono le seguenti:

  • Se una direttiva listen è incompleta, le parti mancanti ottengono i loro valori predefiniti. Ciò significa che l'indirizzo IP e la porta saranno forzati al completamento con i valori predefiniti per poter elaborare la richiesta.
    • In questo caso, un blocco che non contiene alcuna direttiva listen utilizzerà il valore predefinito di 0.0.0.0:80.
    • Un blocco a cui manca una porta e che ha un indirizzo IP pari a 111.111.111.111 diventerà 111.111.111.111:80.
    • Quando non è presente alcun indirizzo IP, un blocco con la porta 8888 acquisirà l'indirizzo IP predefinito da aggiungere per creare 0.0.0.0:8888.
  • Una volta determinati l'indirizzo IP e la porta, Nginx cercherà quindi i blocchi server che corrispondono a quella porta.
  • Se trova solo una corrispondenza specifica, questo sarà il blocco server. Se ci sono più blocchi idonei, Nginx farà riferimento alla direttiva server_name per identificare con precisione l'esatto blocco server in questione.

Nginx ricorrerà alla valutazione della direttiva server_name solo se non ha trovato il blocco server con l'esatto livello di specificità della direttiva listen. Se example.com è sulla porta 80, con un IP di 192.168.1.10, il primo blocco in questo esempio sarà sempre quello che gestisce la richiesta. Questo indipendentemente da ciò che dice la direttiva server_name:

Nginx Server

Se è presente più di un solo blocco di servizio qualificato con una corrispondenza di specificità, allora la direttiva server_name verrà presa in considerazione.

Trova possibili corrispondenze con la direttiva ‘Server_Name’

Se le direttive listen sono ugualmente specifiche, Nginx controllerà l’intestazione ‘Host’ della richiesta. Questo è un valore che conterrà l’IP del dominio che il client cercava inizialmente di raggiungere. Nginx utilizzerà la direttiva server_name all’interno di ciascun blocco server candidato ancora qualificato. Esegue queste valutazioni in base a una formula. È la seguente:

  • Il primo tentativo di Nginx sarà quello di identificare un blocco con un server_name che corrisponda esattamente al valore dell'intestazione ‘Host’ nella richiesta. Se lo trova, il blocco contenente la corrispondenza esatta sarà quello che servirà la richiesta. Nel caso in cui trovi più blocchi, sceglierà il primo della lista.
  • Se non ci sono corrispondenze esatte, Nginx proverà quindi a utilizzare server_name per trovare il blocco server che corrisponde tramite l'uso di *, un carattere jolly all'inizio del nome del blocco server nella configurazione. Trovarne uno con questo metodo significa che il blocco server è stato determinato. Se trova più di una corrispondenza, la corrispondenza più lunga sarà quella che soddisferà la richiesta.
  • Senza una wildcard corrispondente, Nginx proverà a trovare un blocco server con una wildcard finale corrispondente. In altre parole, questo sarà un nome server con un * nella configurazione. Se ne viene trovato uno, viene utilizzato per la richiesta. Mentre, se ne vengono trovati diversi, Nginx utilizzerà ancora una volta la corrispondenza più lunga.
  • Nel caso in cui non vi siano ancora corrispondenze dopo entrambi i tentativi con wildcard, Nginx valuterà quei blocchi server che definiscono il server_name utilizzando espressioni tipiche (indicate da un ~ prima del nome). La prima istanza di server_name con un'espressione corrispondente a quella dell'intestazione ‘Host’ sarà considerata come il blocco server per la gestione della richiesta.
  • Se a questo punto non ci sono ancora corrispondenze, Nginx utilizzerà il blocco server predefinito per quella combinazione di porta e indirizzo IP.

Ogni combinazione porta/indirizzo IP avrà un blocco server designato. Verrà utilizzato se le regole per determinare il blocco server appropriato per la gestione delle richieste sono infruttuose. Questo sarà il primo blocco nella configurazione contenente un'opzione default_server nella direttiva listen (sovrascriverebbe l'algoritmo trovato inizialmente). Ciascuna combinazione indirizzo IP/porta può avere, al massimo, un'impostazione default_server.

Esempi di selezione del blocco server

Se il server_name definito corrisponde esattamente al valore dell'intestazione ‘Host’, sarà il blocco server selezionato per l'elaborazione della richiesta. L'esempio seguente mostra un'intestazione ‘Host’ della richiesta designata come “host1.example.com”. In questo caso, selezionerà il secondo server:

Nginx Server

Senza una corrispondenza esatta, Nginx verificherà se esiste il server_name con un carattere jolly. In caso contrario, verrà selezionata la corrispondenza più lunga che inizia con un carattere jolly. Di seguito, “www.example.org” si trova nell'intestazione “Host”. Ciò significa che sceglierà il secondo blocco:

server screenshot

Senza una corrispondenza che inizia con il carattere jolly, Nginx passa a un controllo del carattere jolly finale. La corrispondenza più lunga che termina con il carattere jolly verrà selezionata per l'elaborazione della richiesta. In questo caso, l'intestazione “Host” è “www.example.com”, quindi sceglierà il terzo blocco server:

Nginx Server

Se ancora non ci sono corrispondenze, Nginx tenterà di far corrispondere le direttive server_name utilizzando espressioni regolari. La prima di queste espressioni viene selezionata per l'elaborazione della richiesta. Se l'“Host” è “www.example.com,” il secondo blocco server sarà la scelta per gestire la richiesta:

Nginx Server

In assenza di corrispondenze, la richiesta verrà indirizzata alla combinazione di indirizzo IP e porta con il server predefinito corrispondente configurato.

Corrispondenza dei blocchi location

Nginx deve inoltre stabilire un algoritmo con cui deciderà quale blocco location sul server sarà responsabile di rispondere a una richiesta.

Sintassi per i blocchi location

Prima di spiegare come Nginx decida come designare il blocco location che gestirà le richieste, esamineremo la sintassi nelle definizioni dei blocchi location. Come affermato in precedenza, i blocchi location risiedono nei blocchi server (e in altri blocchi location). Il loro scopo è prendere decisioni su come elaborare l'URI della richiesta. L'URI è la parte della richiesta che viene dopo l'indirizzo IP e la porta o il nome di dominio nella richiesta.

I blocchi location in genere si presentano così:

Syntax for Location Blocks

Nginx verificherà l'URI della richiesta rispetto a location_match. La presenza o meno del modificatore sopra indicato determinerà il modo in cui Nginx tenterà di far corrispondere i blocchi. A seconda del modificatore, i blocchi location verranno interpretati secondo le seguenti regole:

  • Nessun modificatore: Senza alcun modificatore, la location verrà interpretata come una corrispondenza di prefisso. Ciò significa che la location fornita verrà confrontata con l'inizio dell'URI della richiesta per determinare una corrispondenza corretta.
  • =: Il segno di uguale indica che questo blocco sarà considerato una corrispondenza a condizione che l'URI della richiesta corrisponda esattamente alla location fornita.
  • ~: Il modificatore tilde indica che la corrispondenza del blocco location sarà sensibile alle maiuscole e minuscole.
  • ~*: La combinazione di un modificatore tilde e un asterisco indica che il blocco location non sarà sensibile alle maiuscole e minuscole nella ricerca di una corrispondenza.
  • ^~: Se il modificatore tilde è preceduto da un accento circonflesso (caret), la corrispondenza con espressioni regolari non avverrà a condizione che questo blocco venga scelto come la migliore corrispondenza non basata su espressioni regolari.

Esempi di sintassi del blocco Location

Per presentare un esempio di corrispondenza del prefisso, il blocco location sarà la selezione per rispondere a un URI di una richiesta sotto forma di /site, /site/page1/index.html o /site/index/html:

location site

Ai fini di questa dimostrazione della corrispondenza URI necessaria, il blocco verrà sempre utilizzato per rispondere alle richieste URI sotto forma di /page1, e non all'URI di richiesta /page1/index.html. Se questo è il blocco selezionato e soddisfa la richiesta utilizzando una pagina indice, il gestore effettivo della richiesta verrà reindirizzato internamente a un'altra location:

Nginx Server

Ad esempio, per una location che deve essere interpretata con un'espressione case-sensitive, il blocco seguente non potrebbe gestire le richieste per /FLOWER.PNG. Tuttavia, gestirà le richieste per /tortoise.jpg:

Nginx Server and Location Block Selection Algorithms: Overview

Successivamente, si osservi un blocco che consentirebbe una corrispondenza case-insensitive simile a quello sopra. In questo caso, il blocco potrebbe gestire sia //tortoise.jpg e /FLOWER.PNG:

location

L'ultima variante è quella in cui un blocco impedisce la corrispondenza delle espressioni regolari se viene stabilito che si tratta della corrispondenza ottimale non basata su espressioni regolari. Questa variante può gestire le richieste per /costumes/ninja.html:

Nginx Server and Location Block Selection Algorithms: Overview

Per essere precisi, i modificatori dettano il modo in cui vengono determinati i blocchi location. Questo, tuttavia, non ci dice cosa utilizzi Nginx come algoritmo decisionale per identificare il blocco location a cui inviare una richiesta. Affrontiamo questo aspetto subito dopo.

Scegliere la location che gestirà le richieste di Nginx

Il metodo con cui Nginx sceglie la location che elabora una richiesta è simile a come vengono selezionati i blocchi server. In altre parole, determina la location ottimale per ogni richiesta eseguendo un processo. Al fine di configurare Nginx in modo accurato e adeguato, è fondamentale comprendere questo processo.

Tenendo a mente le dichiarazioni di location affrontate in precedenza, Nginx utilizza allo stesso modo i potenziali contesti di location verificando l'idoneità di ogni location confrontandovi l'URI di una determinata richiesta. In questo, applica il seguente algoritmo:

  • In primo luogo, Nginx controlla tutti i tipi di location che non includono un'espressione regolare. Lo fa cercando tutte le corrispondenze di prefisso basate sulla location. Per fare questo, confronta la location con l'URI completo della richiesta.
  • Nginx inizia a cercare una corrispondenza esatta. Una volta identificato un blocco location che utilizza il modificatore =, questo viene confrontato con l'URI della richiesta. Se i due corrispondono esattamente, il blocco location viene selezionato per gestire la richiesta sul momento.
  • Se non ci sono location che corrispondono esattamente al confronto del modificatore =, Nginx procede a valutare i prefissi che non sono esatti. Una volta determinata la location con il prefisso più lungo che corrisponde all'URI della richiesta, eseguirà le seguenti valutazioni:
    • Se la location con la corrispondenza del prefisso più lungo utilizza il modificatore ^~, questa location verrà scelta immediatamente.
    • Se la location con il prefisso più lungo non utilizza il modificatore ^~, la corrispondenza viene temporaneamente conservata da Nginx per consentire lo spostamento del focus della ricerca.
  • Una volta trovata e memorizzata la corrispondenza della location del prefisso più lungo, Nginx passa alla valutazione delle location con espressioni regolari. Queste includono corrispondenze sia case-sensitive che case-insensitive. Se la location del prefisso corrispondente più lunga contiene al suo interno location regolari, Nginx riformulerà l'elenco per posizionarle vicino all'inizio dell'elenco delle location. La prima espressione dell'elenco riordinato che corrisponde all'URI di una richiesta sarà la location scelta per servire la richiesta.
  • Se non vengono trovate espressioni regolari che soddisfino la richiesta RI, la location memorizzata in precedenza verrà scelta per elaborare la richiesta.

Nginx dà la priorità alle corrispondenze di espressioni regolari rispetto a quelle con prefisso preferenziale per impostazione predefinita. Tuttavia, valuta prima le location con prefisso, in modo che la parte amministrativa possa ignorare questa tendenza con i modificatori = e ^~.

Un altro aspetto importante da considerare è che, mentre le location di prefisso si basano in genere sulla corrispondenza più specifica e più lunga trovata, il controllo di un'espressione regolare si interrompe non appena viene identificata la prima corrispondenza. Ciò significa che il posizionamento all'interno della configurazione ha implicazioni reali per le location di espressioni regolari.

Un ultimo punto da considerare è che le corrispondenze delle espressioni regolari all'interno della corrispondenza con il prefisso più lungo salteranno essenzialmente la fila durante le valutazioni delle location di Nginx. Queste saranno posizionate in cima alla lista e valutate prima delle altre espressioni regolari.

Quando si verifica il passaggio ad altre location nelle valutazioni dei blocchi location?

In genere, una volta valutata una richiesta e selezionato un blocco location per gestirla, essa verrà interamente gestita all'interno di quel contesto. Ciò significa che solo le direttive ereditate e le location selezionate sono i fattori determinanti nell'elaborazione della richiesta, senza alcun contributo da parte dei blocchi location dello stesso livello.

Sebbene questa sia una direttiva generale che consente la progettazione prevedibile dei blocchi location, a volte anche alcune direttive all'interno della location possono attivare una nuova ricerca. In altre parole, la regola del 'solo un blocco location' ha alcune eccezioni. Tali eccezioni potrebbero non essere in linea con le aspettative dei blocchi location. Pertanto,  potrebbero non gestire la richiesta come previsto.

Questi reindirizzamenti interni possono finire per manifestarsi a causa di alcune direttive, tra cui:

  • index
  • rewrite
  • error_page
  • try_files

Se usi la direttiva index, questa risulterà sempre in un reindirizzamento interno durante la gestione della richiesta. Sebbene la ricerca delle corrispondenze di location in genere interrompa l'esecuzione dell'algoritmo per velocizzare il processo di selezione, se la corrispondenza di location trovata è una directory, la richiesta verrà probabilmente reindirizzata a un'altra location per essere elaborata formalmente.

Ad esempio, la seguente prima location corrisponde a un URI di richiesta /exact. Tuttavia, per elaborare la richiesta, la direttiva index ereditata dal blocco location reindirizza la richiesta a un blocco secondario:

index

Per tale scenario, se l'esecuzione deve rimanere all'interno del blocco primario, un altro schema dovrà elaborare la richiesta alla directory. Un modo per farlo consiste nell'impostare un indice non valido per il blocco in questione e attivare invece l'auto index:

location exact

Sebbene questo metodo possa funzionare in alcuni casi, non è generalmente applicabile nella maggior parte dei contesti. Una corrispondenza esatta della directory può essere utile per situazioni in cui la richiesta deve essere riscritta. Questo avvierà una ricerca di location completamente nuova.

Un'altra direttiva che può essere utilizzata per rivalutare la posizione di elaborazione è la direttiva try_files. Essa indica a Nginx di verificare specificamente se esiste un insieme definito di file o directory, con l'ultimo criterio di ricerca che è l'URI a cui Nginx deve reindirizzare internamente.

Consideriamo la seguente configurazione:

root var

Se c'è una richiesta per /blahblah, la prima location la riceverà. Se non viene trovato il file blahblah nella directory /var/www/main, verrà avviata una ricerca successiva per blahblah.html. Poi cercherà una sottodirectory chiamata blahblah nella directory /var/www/main. Se tutti questi controlli falliscono, reindirizzerà a /fallback/index.html. Questo avvierà un'altra ricerca di location che verrà presa in carico da un altro blocco location. Quindi, elaborerà il file /var/www/another/fallback/index.html.

Un'altra direttiva che comporta un reindirizzamento a un altro blocco location è la direttiva rewrite. Nginx cercherà una nuova location corrispondente in base al risultato della direttiva rewrite quando viene utilizzato il parametro last. Se l'ultimo esempio viene modificato per includere ora questa direttiva rewrite, diventa evidente che la richiesta può essere reindirizzata a un'altra location senza che la direttiva try_files venga implementata:

root var ww main

Per questo esempio, la richiesta per /rewrite/hello sarà inizialmente gestita dalla prima location. Dopo essere stata riscritta in /hello, verrà attivata una ricerca secondaria della location. Corrisponderà alla prima location. Verrà elaborata dalla direttiva try_file, tornando potenzialmente a /fallback/index.html se non produce risultati.

Se tuttavia viene effettuata una richiesta per /rewrite/fallback/hello, verrà trovata una corrispondenza con il primo blocco. Pertanto, la riscrittura verrà elaborata nuovamente, ma questa volta produrrà /fallback/hello come risultato. La richiesta verrà elaborata su un altro blocco location.

Situazioni simili si verificano quando si utilizza la direttiva return per inviare codici di stato 301 o 302. L'unica differenza è che ne consegue una nuova richiesta, che si manifesta in un reindirizzamento molto evidente. Allo stesso modo, questo può accadere con la direttiva rewrite quando si applicano i flag permanent o redirect.

Un’altra direttiva che può portare a reindirizzamenti interni simili a quelli di try_again è la direttiva error_page. È possibile utilizzarla quando si riscontrano particolari codici di errore durante l’elaborazione. Quando viene impostata una direttiva try_files, la direttiva error_page probabilmente non verrà mai eseguita. Questo perché tale direttiva gestirà l’intero ciclo di vita della richiesta.

Consideriamo il seguente esempio:

root screenshot

In questo caso, ogni richiesta verrà elaborata dal primo blocco che serve i file da /var/www/main. Questo non si applica alle richieste che iniziano con /another. Ma se un file non dovesse essere trovato, verrà avviato un reindirizzamento interno verso /another/whoops/html. Questo porterà a un'altra ricerca di location. A sua volta, indirizzerà la richiesta a un blocco secondario, con quel file che verrà servito da /var/www/another/whoops.html.

Come è evidente, la comprensione delle situazioni in cui Nginx attiverà una nuova ricerca di location può aiutare a prevedere meglio il comportamento del sistema durante l'elaborazione delle richieste.

Conclusione

Il lavoro degli amministratori diventa immensamente più semplice quando comprendono i metodi con cui Nginx gestisce le richieste dei client. Questo consente agli amministratori di accertare a quale blocco server sarà indirizzata la richiesta. Possono anche determinare il blocco location che verrà selezionato in base all'URI della richiesta. In generale, offre inoltre agli amministratori la possibilità di tracciare i contesti applicati da Nginx durante la gestione di ciascuna richiesta.

Infine, puoi dare un'occhiata agli altri tutorial su nostro blogincentrati su Nginx. Ti aiuteranno a trarre un maggiore vantaggio da uno dei server web più popolari al mondo:

Buon computing!

author

Manpreet Singh

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.