Späť na blog

Algoritmy výberu blokov Server a Location v Nginx: Prehľad

Algoritmy výberu blokov Server a Location v Nginx: Prehľad

Úvod

Nginx patrí medzi najpopulárnejšie webové servery na svete. Dokáže úspešne zvládnuť veľké množstvo súčasných klientskych pripojení. Zároveň funguje ako poštový, webový alebo reverzný proxy server.

Cieľom tejto príručky je načrtnúť zákulisné metódy, ktoré riadia to, ako Nginx spracováva požiadavky klientov. Demystifikujeme konštrukciu server a location blokov, ako aj vysvetlíme, ako najlepšie znížiť zdanlivú nepredvídateľnosť spracovania požiadaviek.

V prvom rade, tu je komplexný návod na ako nainštalovať Nginx na váš server Ubuntu. Teraz poďme na to!

Konfigurácia blokov v Nginx

Logický prístup Nginx zahŕňa triedenie konfigurácií určených na rôzne účely do samostatných, logickejších obsahových blokov. Tie budú usporiadané v hierarchickej štruktúre. Keď klient vytvorí požiadavku, Nginx spustí proces, ktorým určí, ktoré z týchto konfiguračných blokov sú najvhodnejšie na vybavenie tejto požiadavky. Zameriame sa na tento rozhodovací proces.

Primárne bloky, o ktorých budeme diskutovať, budú server bloky a location bloky. Bloky server sú podmnožinou konfigurácií, ktoré Nginx vytvára a ktoré definujú, ktorý virtuálny server bude zodpovedný za spracovanie definovaného typu požiadavky. Najčastejšie sú založené na IP adrese, doménovom mene alebo porte prichádzajúcej požiadavky. Správcovia konfigurujú viacero blokov server. Potom sa musia rozhodnúť, ktoré z pripojení by malo požiadavku spracovať.

Bloky location sa nachádzajú v rámci blokov server. Tieto bloky rozhodujú o tom, ako a ktoré zdroje môžete využiť na spracovanie prichádzajúcich požiadaviek na ich konkrétny nadradený server. Tento model je vysoko flexibilný. Priestor URI môže byť nakonfigurovaný tak, aby využíval tieto bloky akýmkoľvek spôsobom, ktorý správca považuje za najlepší.

Rozhodovanie o tom, ktorý blok spracuje ktorú požiadavku v Nginx

Nginx umožňuje definovať viacero blokov server. Všetky fungujú ako rôzne virtuálne webové servery. Preto musí existovať metóda, ktorá určí, ktorý server bude riešiť konkrétne prichádzajúce požiadavky. To sa dosahuje hľadaním najvhodnejšieho riešenia pre vybavenie požiadavky prostredníctvom systému definovaných kontrol.

Nginx sa primárne zaoberá dvoma hlavnými smernicami bloku server: listen a server_name.

Hľadanie možných zhôd pomocou smernice „Listen“

Prvá vec, ktorú Nginx vyhodnocuje, je port a IP adresa požiadavky. Potom ich porovná so smernicou listen každého servera. Táto analýza zoznamu serverov pomáha izolovať iba tie bloky server, ktoré dokážu danú požiadavku vyriešiť.

Smernica listen zvyčajne definuje port a IP adresu, na ktoré bude konkrétny blok server zodpovedný odpovedať. Blok server, ktorý neobsahuje smernicu listen, predvolene získa parametre listen 0.0.0.0:80. Ak Nginx spúšťa bežný používateľ bez práv root, parameter listen je definovaný ako 0.0.0.0:8080. To znamená, že bez ohľadu na rozhranie, ak požiadavky prichádzajú z portu 80, bloky definované takýmto spôsobom na ne budú odpovedať. Táto predvolená hodnota však nemá veľkú váhu v procese výberu servera.

Smernicu listen môžete nakonfigurovaf na:

  • Samostatnú IP adresu, ktorá počúva požiadavky na predvolenom porte (80).
  • Samostatný port, ktorý počúva na akomkoľvek rozhraní na tomto porte.
  • Kombináciu portu a IP adresy.
  • Nastavenú cestu k soketu Unix (táto možnosť má význam len vtedy, keď požiadavky prechádzajú cez rôzne servery).

Nginx pri rozhodovaní o tom, do ktorého bloku server sa pošle požiadavka, uplatní súbor pravidiel. Pravidlá závisia od konkrétnej konfigurácie smernice listen. Sú nasledovné:

  • Ak je smernica listen neúplná, chýbajúce časti získajú svoje predvolené hodnoty. To znamená, že IP adresa a port budú na účely spracovania požiadavky povinne doplnené predvolenými hodnotami.
    • V tomto prípade blok, ktorý neobsahuje žiadnu smernicu listen, použije predvolenú hodnotu 0.0.0.0:80.
    • Blok, ktorému chýba port a má IP adresu 111.111.111.111, sa zmení na 111.111.111.111:80.
    • Ak neexistuje žiadna IP adresa, blok s portom 8888 získa predvolenú IP adresu, ktorá sa pripojí a vytvorí 0.0.0.0:8888.
  • Po určení IP adresy a portu bude Nginx hľadať serverové bloky ponúkané ako zhoda pre tento port.
  • Ak nájde iba jednu konkrétnu zhodu, bude to tento serverový blok. Ak existuje viacero vyhovujúcich blokov, Nginx sa obráti na direktívu server_name, aby podrobnejšie určil presný serverový blok.

Nginx pristúpi k vyhodnocovaniu direktívy server_name iba vtedy, ak nenašiel serverový blok s presnou úrovňou špecifickosti z direktívy listen. Ak je example.com na porte 80 s IP adresou 192.168.1.10, prvý blok v tomto príklade bude vždy ten, ktorý spracuje požiadavku. Je to tak bez ohľadu na to, čo hovorí direktíva server_name:

Nginx Server

Ak existuje viac ako len jeden vyhovujúci serverový blok so zhodou špecifickosti, potom sa vezme do úvahy direktíva server_name.

Nájdite možné zhody pomocou direktívy ‘Server_Name’

Ak sú direktívy listen rovnako špecifické, Nginx skontroluje hlavičku ‘Host’ požiadavky. Ide o hodnotu, ktorá bude obsahovať IP adresu domény, ktorú sa klient pôvodne pokúšal dosiahnuť. Nginx použije direktívu server_name vo vnútri každého stále vyhovujúceho kandidáta na serverový blok. Tieto vyhodnotenia vykonáva na základe vzorca. Ten je nasledovný:

  • Prvým pokusom Nginx bude identifikovať blok s server_name, ktorý sa presne zhoduje s hodnotou hlavičky ‘Host’ v požiadavke. Ak ho nájde, blok obsahujúci presnú zhodu bude ten, ktorý obslúži požiadavku. V prípade, že nájde viacero blokov, vyberie prvý v zozname.
  • Ak neexistujú žiadne presné zhody, Nginx sa potom pokúsi použiť server_name na nájdenie serverového bloku, ktorý sa zhoduje s použitím *, zástupného znaku na začiatku názvu serverového bloku v konfigurácii. Nájdenie bloku touto metódou znamená, že serverový blok bol určený. Ak nájde viac ako jednu zhodu, požiadavku splní tá najdlhšia zhoda.
  • Bez zhodného zástupného znaku sa Nginx pokúsi nájsť serverový blok so zhodným koncovým zástupným znakom. Inými slovami, pôjde o názov servera s * na konci v konfigurácii. Ak sa taký nájde, použije sa pre požiadavku. Ak ich však nájdete viacero, Nginx opäť použije najdlhšiu zhodu.
  • V prípade, že ani po oboch pokusoch so zástupnými znakmi stále neexistujú žiadne zhody, Nginx vyhodnotí tie serverové bloky, ktoré definujú server_name pomocou regulárnych výrazov (označených znakom ~ pred názvom). Prvý výskyt server_name s výrazom zodpovedajúcim hlavičke ‘Host’ bude považovaný za serverový blok na spracovanie požiadavky.
  • Ak v tomto bode stále neexistujú žiadne zhody, Nginx použije predvolený serverový blok pre túto kombináciu portu a IP adresy.

Každá kombinácia portu/IP adresy bude mať určený serverový blok. Použije sa, ak sú pravidlá určovania príslušného serverového bloku na spracovanie požiadaviek bezvýsledné. Pôjde o prvý blok v konfigurácii obsahujúci voľbu default_server v direktíve listen (prepísal by pôvodne nájdený algoritmus). Každá kombinácia IP adresy/portu môže mať maximálne jedno nastavenie default_server.

Príklady výberu serverového bloku

Ak sa definovaný server_name presne zhoduje s hodnotou hlavičky ‘Host’, bude to serverový blok vybraný na spracovanie požiadavky. Nasledujúci príklad ukazuje hlavičku ‘Host’ požiadavky označenú ako „host1.example.com“. V tomto prípade vyberie druhý server:

Nginx Server

Bez presnej zhody Nginx skontroluje, či existuje server_name so zástupným znakom. Ak nie, vyberie sa najdlhšia zhoda začínajúca zástupným znakom. V nasledujúcom texte „www.example.org“ sa nachádza v hlavičke „Host“. To znamená, že vyberie druhý blok:

server screenshot

Bez zhody začínajúcej so zástupným znakom prejde Nginx na kontrolu koncového zástupného znaku. Pre spracovanie požiadavky sa vyberie najdlhšia zhoda končiaca zástupným znakom. V tomto prípade je hlavička „Host“ „www.example.com“, takže si vyberie tretí blok servera:

Nginx Server

Ak stále neexistujú žiadne zhody, Nginx sa pokúsi porovnať direktívy server_name pomocou štandardných výrazov. Prvý z týchto výrazov sa vyberie na spracovanie požiadavky. Ak je „Host“ „www.example.com,” na vybavenie požiadavky sa vyberie druhý blok servera:

Nginx Server

Ak stále nedôjde k zhode, požiadavka prejde na kombináciu IP adresy a portu s nastaveným zodpovedajúcim predvoleným serverom.

Porovnávanie blokov Location

Nginx tiež musí stanoviť algoritmus, podľa ktorého rozhodne, ktorý blok location na serveri bude zodpovedný za odpoveď na požiadavku.

Syntax pre bloky Location

Pred vysvetlením, ako Nginx rozhoduje o určení bloku location, ktorý bude spracovávať požiadavky, si zopakujeme syntax v definíciách blokov location. Ako už bolo spomenuté, bloky location sa nachádzajú v blokoch server (a iných blokoch location). Ich účelom je rozhodovať o tom, ako spracovať URI požiadavky. URI je časť požiadavky, ktorá nasleduje za IP adresou a portom alebo názvom domény v požiadavke.

Bloky location zvyčajne vyzerajú takto:

Syntax for Location Blocks

Nginx skontroluje URI požiadavky voči location_match. To, či je prítomný vyššie uvedený modifikátor, určí spôsob, akým sa Nginx pokúsi porovnať bloky. V závislosti od modifikátora budú bloky location interpretované podľa nasledujúcich pravidiel:

  • Bez modifikátorov: Bez akýchkoľvek modifikátorov sa location bude interpretovať ako prefixová zhoda. To znamená, že poskytnutá location sa bude porovnávať so začiatkom URI v požiadavke, aby sa určila správna zhoda.
  • =: Znak rovnosti znamená, že tento blok sa bude považovať za zhodný, pokiaľ sa URI požiadavky presne zhoduje s poskytnutou location.
  • ~: Modifikátor vlnovky (tilde) predstavuje, že zhoda bloku location bude rozlišovať malé a veľké písmená.
  • ~*: Kombinácia modifikátorov vlnovky a hviezdičky predstavuje, že blok location nebude pri hľadaní zhody rozlišovať malé a veľké písmená.
  • ^~: Ak pred modifikátorom vlnovky predchádza strieška, porovnávanie regulárnych výrazov neprebehne, pokiaľ bude tento blok vybraný ako najlepšia zhoda bez regulárnych výrazov.

Príklady syntaxe bloku Location

Ako príklad prefixovej zhody, blok location bude vybraný na odpoveď na URI požiadavky vo formáte /site, /site/page1/index.html alebo /site/index/html:

location site

Pre účely tejto ukázky požadovanej zhody URI sa blok vždy použije na odpoveď na požiadavky URI vo formáte /page1, a nie na požiadavku URI /page1/index.html. Ak je toto vybraný blok a splní požiadavku pomocou indexovej stránky, skutočný spracovateľ požiadavky bude interne presmerovaný na inú location:

Nginx Server

Napríklad pre location, ktorá sa musí interpretovať s výrazom rozlišujúcim malé a veľké písmená, by nasledujúci blok nemohol spracovať požiadavky na /FLOWER.PNG. Bude však spracovávať požiadavky na /tortoise.jpg:

Nginx Server and Location Block Selection Algorithms: Overview

Ďalej si všimnite blok, ktorý by umožňoval zhodu bez rozlišovania veľkosti písmen, podobný tomu vyššie. V tomto prípade by blok mohol spracovať ako //tortoise.jpg a /FLOWER.PNG:

location

Posledným variantom je variant, v ktorom by blok zabránil porovnávaniu regulárnych výrazov, ak sa určí, že ide o optimálnu zhodu bez regulárnych výrazov. Tento môže spracovávať požiadavky na /costumes/ninja.html:

Nginx Server and Location Block Selection Algorithms: Overview

Presnejšie povedané, modifikátory určujú spôsob, akým sa rozhoduje o blokoch location. To nám však nehovorí, čo Nginx používa ako rozhodovací algoritmus na identifikáciu bloku location, do ktorého sa má požiadavka odoslať. Venujme sa tomu ďalej.

Výber location, ktorá bude spracovávať požiadavky v Nginx

Metóda, ktorou Nginx vyberá umiestnenie (location), ktoré spracováva požiadavku, je podobná tomu, ako sa vyberajú bloky servera. Inými slovami, optimálne umiestnenie pre každú požiadavku určuje spustením procesu. Na to, aby ste nakonfigurovali Nginx presne a zodpovedajúco, je nevyhnutné, aby ste tomuto procesu porozumeli.

S ohľadom na skôr spomenuté deklarácie location, Nginx podobne využíva potenciálne kontexty location tak, že kontroluje spôsobilosť pre každé umiestnenie porovnaním URI z danej požiadavky. Pri tom uplatňuje nasledujúci algoritmus:

  • Najprv Nginx skontroluje všetky typy location, ktoré neobsahujú regulárny výraz. Robí to tak, že vyhľadáva všetky zhody prefixov na základe umiestnenia. Aby to dosiahol, porovnáva location s kompletnou URI požiadavky.
  • Nginx začne hľadať presnú zhodu. Akonáhle je identifikovaný blok location, ktorý používa modifikátor =, porovná sa s požiadavkou URI. Ak sa tieto dva presne zhodujú, blok location sa okamžite vyberie na spracovanie požiadavky.
  • Ak neexistujú žiadne umiestnenia, ktoré by presne zodpovedali porovnaniu s modifikátorom =, Nginx prejde k vyhodnocovaniu nepresných prefixov. Akonáhle určí location s najdlhším prefixom, ktorý sa zhoduje s URI požiadavky, vykoná nasledujúce vyhodnotenia:
    • Ak location s najdlhšou zhodou prefixu používa modifikátor ^~, toto umiestnenie sa okamžite vyberie.
    • Ak location s najdlhším prefixom nepoužíva modifikátor ^~, Nginx si túto zhodu dočasne uchová, aby sa mohlo zmeniť zameranie vyhľadávania.
  • Akonáhle sa nájde a uloží najdlhšia zhoda prefixu location, Nginx prejde na vyhodnocovanie umiestnení s regulárnymi výrazmi. Tie zahŕňajú zhody rozlišujúce aj nerozlišujúce veľkosť písmen. Ak najdlhšie sa zhodujúce umiestnenie prefixu obsahuje nejaké regulárne umiestnenia, Nginx preusporiada zoznam tak, aby ich umiestnil blízko začiatku zoznamu umiestnení. Prvý výraz z preusporiadaného zoznamu, ktorý sa zhoduje s URI požiadavky, bude vybraným umiestnením na obsluhu požiadavky.
  • Ak sa nenájdu žiadne regulárne výrazy, ktoré by vyhovovali požiadavke RI, na spracovanie požiadavky sa vyberie predtým uložené umiestnenie.

Nginx predvolene uprednostňuje zhody regulárnych výrazov pred prioritnými prefixovými zhodami. Najprv však vyhodnocuje prefixové umiestnenia, aby administrátor mohol túto tendenciu potlačiť pomocou modifikátorov = a ^~.

Ďalším dôležitým poznatkom je, že zatiaľ čo prefixové umiestnenia sú zvyčajne založené na najšpecifickejšej, najdlhšej nájdenej zhode, kontrola regulárnych výrazov sa zastaví hneď, ako sa identifikuje prvá zhoda. To znamená, že umiestnenie v rámci konfigurácie má reálny vplyv na umiestnenia s regulárnymi výrazmi.

Posledným bodom, ktorý treba spomenúť, je, že zhody regulárnych výrazov v rámci zhody s najdlhším prefixom v podstate predbehnú rad počas vyhodnocovania location v Nginxe. Tieto budú umiestnené na začiatku zoznamu a vyhodnotené pred ostatnými regulárnymi výrazmi.

Kedy dochádza k prechodu na iné umiestnenia pri vyhodnocovaní blokov location?

Zvyčajne platí, že akonáhle je požiadavka posúdená a je vybraný blok location na jej spracovanie, bude sa riešiť výhradne v tomto kontexte. To znamená, že pri spracovaní požiadavky rozhodujú iba zdedené direktívy a vybrané umiestnenia, bez akéhokoľvek vplyvu súrodeneckých blokov location.

Hoci ide o všeobecné pravidlo, ktoré umožňuje predvídateľný návrh blokov location, niekedy môžu určité direktívy v rámci location spustiť aj nové vyhľadávanie. Inými slovami, pravidlo „iba jedného bloku location“ má niekoľko výnimiek. Tieto výnimky nemusia byť v súlade s očakávaniami blokov location. Preto nemusia vyriešiť požiadavku podľa očakávania.

Tieto interné presmerovania sa môžu prejaviť v dôsledku niektorých direktív vrátane:

  • index
  • rewrite
  • error_page
  • try_files

Ak použijete direktívu index, vždy to povedie k internému presmerovaniu počas spracovania požiadavky. Zatiaľ čo hľadanie zhody location zvyčajne ukončí vykonávanie algoritmu, aby sa urýchlil proces výberu, ak je nájdená zhoda location adresárom, požiadavka bude pravdepodobne presmerovaná na iné location, aby bola formálne spracovaná.

Napríklad nasledujúci prvý location zodpovedá URI požiadavky /exact. Na spracovanie požiadavky však direktíva index, ktorú blok location dedí, presmeruje požiadavku do sekundárneho bloku:

index

Pre tento scenár, ak je potrebné, aby vykonávanie zostalo v primárnom bloku, bude musieť požiadavku do adresára spracovať iná schéma. Jedným zo spôsobov, ako to urobiť, je nastaviť neplatný index pre príslušný blok a namiesto toho aktivovať auto index:

location exact

Hoci táto metóda môže v niekoľkých prípadoch fungovať, vo väčšine kontextov nie je vo všeobecnosti prakticky použiteľná. Presná zhoda adresára môže byť užitočná v situáciách, keď je potrebné požiadavku prepísať. To spustí úplne nové vyhľadávanie location.

Ďalšou direktívou, ktorú možno použiť na prehodnotenie spracovávaného location, je direktíva try_files. Hovorí Nginxu, aby konkrétne skontroloval, či existuje definovaná sada súborov alebo adresárov, pričom posledným kritériom vyhľadávania je URI, na ktoré má Nginx interne presmerovať.

Pozrime sa na nasledujúcu konfiguráciu:

root var

Ak príde požiadavka na /blahblah, prijme ju prvý location. Nenájdenie súboru blahblah v adresári /var/www/main spustí následné vyhľadávanie blahblah.html. Potom sa bude hľadať podadresár s názvom blahblah v adresári /var/www/main. Ak všetky tieto kontroly zlyhajú, presmeruje sa na /fallback/index.html. To spustí ďalšie vyhľadávanie location, ktoré zachytí iný blok location. Potom spracuje súbor /var/www/another/fallback/index.html.

Ďalšou direktívou, ktorá vedie k presmerovaniu na iný blok location, je direktíva rewrite. Nginx vyhľadá nové vyhovujúce location na základe výsledku direktívy rewrite, keď sa použije parameter last. Ak sa predchádzajúci príklad upraví tak, aby teraz obsahoval túto direktívu rewrite, je zrejmé, že požiadavka môže byť presmerovaná na iné location bez implementácie direktívy try_files:

root var ww main

V tomto príklade bude požiadavka na /rewrite/hello najskôr adresovaná prvému location. Po jej prepísaní na /hello sa spustí sekundárne vyhľadávanie location. To sa zhoduje s prvým location. Bude spracovaná direktívou try_file, s potenciálnym návratom k /fallback/index.html, ak neprinesie žiadne výsledky.

Ak sa však uskutoční požiadavka na /rewrite/fallback/hello, nájde sa zhoda s prvým blokom. Prepísanie (rewrite) sa teda spracuje znova, ale tentoraz prinesie ako výsledok /fallback/hello. Požiadavka bude spracovaná v inom bloku location.

K podobným situáciám dochádza, keď použijete direktívu return na odoslanie stavových kódov 301 alebo 302. Jediným rozdielom je, že vznikne nová požiadavka, čo sa prejaví veľmi zjavným presmerovaním. Podobne k tomu môže dôjsť pri direktíve rewrite, keď použijete príznaky permanent alebo redirect.

Ďalšou direktívou, ktorá môže viesť k podobným interným presmerovaniam ako try_again, je direktíva error_page. Môžete ju použiť, keď pri spracovaní narazíte na konkrétne chybové kódy. Keď je nastavená direktíva try_files, direktíva error_page sa pravdepodobne nikdy nevykoná. Je to preto, že táto direktíva spracuje celý životný cyklus požiadavky.

Pozrime sa na nasledujúci príklad:

root screenshot

V tomto prípade bude každá požiadavka spracovaná prvým blokom, ktorý poskytuje súbory z /var/www/main. To neplatí pre požiadavky, ktoré začínajú na /another. Ak by sa však súbor nenašiel, spustí sa interné presmerovanie na /another/whoops/html. To povedie k ďalšiemu vyhľadávaniu location. To zasa nasmeruje požiadavku na sekundárny blok, pričom tento súbor bude adresovaný z /var/www/another/whoops.html.

Ako je zrejmé, pochopenie situácií, kedy Nginx spustí nové vyhľadávanie location, môže pomôcť lepšie predpovedať správanie systému pri spracovaní požiadaviek.

Záver

Práca administrátorov sa nesmierne zjednoduší, keď pochopia metódy, ktorými Nginx spracováva požiadavky klientov. To administrátorom umožňuje zistiť, do ktorého bloku servera požiadavka pôjde. Môžu tiež určiť blok location, ktorý bude vybraný na základe URI požiadavky. Celkovo to administrátorom poskytuje aj možnosť sledovať kontexty aplikované Nginxom pri spracovaní každej požiadavky.

Na záver si môžete pozrieť ďalšie návody na našom blogu zamerané na Nginx. Pomôžu vám lepšie využiť jeden z najpopulárnejších webových serverov na svete:

Príjemnú prácu!

author

Manpreet Singh

Autor · CloudSigma

Preslav Dobrev je kreatívny dizajnér v spoločnosti CloudSigma, ktorý sa zameriava na konzistentnú firemnú identitu prostredníctvom tradičných a inovatívnych marketingových kanálov. Dokáže brilantne spájať umeleckú víziu so strategickým marketingom, čím vytvára pôsobivé príbehy značky.

Komentáre

Zatiaľ žiadne komentáre. Buďte prvý.