Terug naar blog

Nginx Server- en Location Block-selectiealgoritmen: Overzicht

Nginx Server- en Location Block-selectiealgoritmen: Overzicht

Inleiding

Nginx behoort tot de populairste webserveropties ter wereld. Het is in staat om succesvol om te gaan met een veelvoud aan gelijktijdige clientverbindingen. Tegelijkertijd functioneert het als een mail-, web- of reverse proxy-server.

Deze gids is bedoeld om de methoden achter de schermen te schetsen die bepalen hoe Nginx verzoeken van clients verwerkt. We zullen het server- en locatie-blok-ontwerp demystificeren, en uitleggen hoe u de schijnbare onvoorspelbaarheid van het afhandelen van verzoeken het beste kunt verminderen.

Eerst en vooral is hier een uitgebreide handleiding over hoe u Nginx installeert op uw Ubuntu-server. Laten we nu beginnen!

Blokconfiguratie met Nginx

De logische benadering van Nginx houdt in dat de configuraties die voor verschillende doeleinden zijn bedoeld, worden gesorteerd in afzonderlijke, logischere inhoudsblokken. Deze bevinden zich in een hiërarchische structuur. Wanneer een client een verzoek indient, start Nginx een proces waarmee het bepaalt welke van deze configuratieblokken het meest geschikt zijn om dit verzoek af te handelen. We zullen ons concentreren op dit besluitvormingsproces.

De belangrijkste blokken die we bespreken zijn server-blokken en location-blokken. Serverblokken zijn een subset van de configuraties die Nginx instelt en die bepalen welke virtuele server verantwoordelijk is voor het afhandelen van een gedefinieerd type verzoek. Ze zijn meestal gebaseerd op het IP-adres, de domeinnaam of de poort van het binnenkomende verzoek. Beheerders configureren meerdere serverblokken. Vervolgens moeten ze beslissen welke van de verbindingen het verzoek moet afhandelen.

Location-blokken bevinden zich binnen de serverblokken. Dit zijn de beslissers over hoe en welke bronnen u kunt inzetten om de binnenkomende verzoeken naar hun specifieke bovenliggende server af te handelen. Dit model is uiterst flexibel. De URI-ruimte kan worden geconfigureerd om deze blokken te gebruiken op de manier die de beheerder het beste vindt.

Beslissen welk blok welk verzoek afhandelt met Nginx

Nginx maakt het mogelijk om meerdere serverblokken te definiëren. Ze functioneren allemaal als verschillende virtuele webservers. Daarom is er een methode nodig die bepaalt welke server specifieke binnenkomende verzoeken zal afhandelen. Dit wordt gedaan door de beste match voor de verzoekprestaties te vinden via een systeem van gedefinieerde controles.

Nginx werkt voornamelijk met twee belangrijke serverblok-richtlijnen: listen en server_name.

Mogelijke overeenkomsten vinden met de 'Listen'-richtlijn

Het eerste dat Nginx evalueert, is de poort en het IP-adres van het verzoek. Vervolgens vergelijkt het dit met de listen-richtlijn van elke server. Dit parseren van de serverlijst helpt om alleen die serverblokken te isoleren die het betreffende verzoek kunnen afhandelen.

Meestal definieert de listen-richtlijn de poort en het IP-adres waarop een specifiek serverblok verantwoordelijk is voor het reageren. Een serverblok dat geen listen-richtlijn bevat, ontvangt standaard de listen-parameters 0.0.0.0:80. Als Nginx wordt uitgevoerd door een normale, niet-rootgebruiker, is de listen-parameter gedefinieerd als 0.0.0.0:8080. Dat betekent dat, ongeacht de interface, als de blokken van poort 80 komen, op deze manier gedefinieerde blokken daarop zullen reageren. Deze standaardwaarde weegt echter niet zwaar mee in het proces van het selecteren van een server.

U kunt de listen-richtlijn configureren voor:

  • Een enkel IP-adres dat luistert naar verzoeken op de standaardpoort (80).
  • Een enkele poort die luistert naar elke interface op die poort.
  • Een combinatie van poort en IP-adres.
  • Een ingesteld Unix-socketpad (deze optie heeft alleen gevolgen wanneer verzoeken over verschillende servers worden doorgegeven).

Nginx zal een reeks regels toepassen bij het beslissen naar welk serverblok een verzoek wordt verzonden. De regels zijn afhankelijk van de specifieke configuratie van de listen-richtlijn. Ze zijn als volgt:

  • Als een listen-richtlijn onvolledig is, krijgen de ontbrekende delen hun standaardwaarden. Dit betekent dat het IP-adres en de poort gedwongen worden aangevuld met standaardwaarden om het verzoek te kunnen verwerken.
    • In dit geval zal een blok dat geen listen-richtlijn bevat, de standaardwaarde 0.0.0.0:80 gebruiken.
    • Een blok dat een poort mist en een IP-adres van 111.111.111.111 heeft, wordt 111.111.111.111:80.
    • Wanneer er geen IP-adres is, krijgt een blok met poort 8888 het standaard IP-adres om toe te voegen om zo 0.0.0.0:8888 te maken.
  • Met het vastgestelde IP-adres en de poort zal Nginx vervolgens zoeken naar serverblokken die als match voor die poort worden aangeboden.
  • Als het slechts één specifieke match vindt, is dit het serverblok. Als er meerdere blokken in aanmerking komen, zal Nginx zich wenden tot de server_name-richtlijn om verder in te zoomen op het exacte serverblok in kwestie.

Nginx zal pas overgaan tot het evalueren van de server_name-richtlijn als het niet het serverblok met het exacte specificiteitsniveau van de listen-richtlijn heeft gevonden. Als example.com op poort 80 staat, met een IP van 192.168.1.10, zal het eerste blok in dit voorbeeld altijd degene zijn die het verzoek afhandelt. Dit is het geval ongeacht wat de server_name-richtlijn zegt:

Nginx Server

Als er meer dan één gekwalificeerd serviceblok is met een overeenkomstige specificiteit, dan zal de server_name-richtlijn in overweging worden genomen.

Mogelijke matches vinden met de ‘Server_Name’-richtlijn

Als de listen-richtlijnen even specifiek zijn, zal Nginx de header van het verzoek’s ‘Host’ controleren. Dit is een waarde die in eerste instantie het IP-adres bevat van het domein dat de client probeerde te bereiken. Nginx zal de server_name-richtlijn gebruiken binnen elk nog gekwalificeerd kandidaat-serverblok. Het voert deze evaluaties uit op basis van een formule. Deze is als volgt:

  • Nginx’s eerste poging zal zijn om een blok te identificeren met een server_name die exact overeenkomt met de ‘Host’-headerwaarde in het verzoek. Als het deze vindt, zal het blok met de exacte match degene zijn die het verzoek afhandelt. In het geval dat het meerdere blokken vindt, kiest het de eerste op de lijst.
  • Als er geen exacte matches zijn, zal Nginx proberen server_name te gebruiken om het serverblok te vinden dat overeenkomt met het gebruik van *, een wildcard aan het begin van de serverbloknaam in de configuratie. Het vinden van een blok met deze methode betekent dat het serverblok is bepaald. Als het meer dan één match vindt, zal de langste match degene zijn die het verzoek afhandelt.
  • Zonder een overeenkomende wildcard zal Nginx proberen een serverblok te vinden met een overeenkomende wildcard aan het einde. Met andere woorden, dit is een servernaam met een * in de configuratie. Als er een wordt gevonden, wordt deze gebruikt voor het verzoek. Als u er echter meerdere vindt, zal Nginx opnieuw de langste match gebruiken.
  • In het geval dat er na beide wildcard-pogingen nog steeds geen matches zijn, zal Nginx die serverblokken evalueren die de server_name definiëren met behulp van reguliere expressies (aangeduid met een ~ voor de naam). De eerste instantie van server_name met een expressie die overeenkomt met die van de ‘Host’-header, zal worden beschouwd als het serverblok voor de afhandeling van het verzoek.
  • Als er op dit punt nog steeds geen matches zijn, zal Nginx het standaard serverblok gebruiken voor die combinatie van poort en IP-adres.

Elke poort/IP-adrescombinatie heeft een toegewezen serverblok. Dit wordt gebruikt als de regels voor het bepalen van het juiste serverblok voor de verzoekafhandeling vruchteloos zijn. Dit is het eerste blok in de configuratie dat een default_server-optie bevat in de listen-richtlijn (dit zou het aanvankelijk gevonden algoritme overschrijven). Elke IP-adres/poortcombinatie kan maximaal één default_server-instelling hebben.

Voorbeelden van serverblokselectie

Als de gedefinieerde server_name exact overeenkomt met de ‘Host’-headerwaarde, zal dit het geselecteerde serverblok zijn voor de verwerking van het verzoek. Het volgende voorbeeld toont een ‘Host’-header van het verzoek aangeduid als “host1.example.com”. In dit geval zal het de tweede server selecteren:

Nginx Server

Zonder een exacte match zal Nginx controleren of de server_name met een wildcard bestaat. Zo niet, dan wordt de langste match die begint met een wildcard geselecteerd. In het volgende is “www.example.org” aanwezig op de “Host”-header. Dat betekent dat het het tweede blok zal kiezen:

server screenshot

Zonder een match die begint met de wildcard, gaat Nginx over op een controle van wildcards aan het einde. De langste match die eindigt met de wildcard wordt geselecteerd voor de verwerking van het verzoek. In dit geval is de “Host”-header “www.example.com”, dus zal het het derde serverblok kiezen:

Nginx Server

Als er nog steeds geen matches zijn, zal Nginx proberen server_name-richtlijnen te matchen met behulp van standaardexpressies. De eerste van die expressies wordt geselecteerd voor de verwerking van het verzoek. Als de “Host” “www.example.com,” dan is het tweede serverblok de keuze om het verzoek af te handelen:

Nginx Server

Als er nog steeds geen matches zijn, gaat het verzoek naar de IP-adres- en poortcombinatie met de bijbehorende ingestelde standaardserver.

Location-blokken matchen

Nginx moet ook een algoritme bepalen waarmee het beslist welk location-blok op de server verantwoordelijk is voor het beantwoorden van een verzoek.

Syntaxis voor location-blokken

Voordat we uitleggen hoe Nginx beslist hoe het location-blok dat verzoeken afhandelt wordt aangewezen, bekijken we de syntaxis in definities van location-blokken. Zoals eerder vermeld, bevinden location-blokken zich in serverblokken (en andere location-blokken). Hun doel is om beslissingen te nemen over hoe de URI van het verzoek moet worden verwerkt. De URI is het deel van het verzoek dat na het IP-adres en de poort of de domeinnaam in het verzoek komt.

Location-blokken zien er doorgaans als volgt uit:

Syntax for Location Blocks

Nginx controleert de URI van het verzoek aan de hand van de location_match. Of de bovenstaande modifier wel of niet aanwezig is, bepaalt de manier waarop Nginx zal proberen de blokken te matchen. Afhankelijk van de modifier worden de location-blokken geïnterpreteerd volgens de volgende regels:

  • Geen modifiers: Zonder modifiers wordt de locatie geïnterpreteerd als een prefix-match. Dit betekent dat de opgegeven locatie wordt vergeleken met het begin van de URI van het verzoek om een correcte match te bepalen.
  • =: Het isgelijkteken geeft aan dat dit blok als een match wordt beschouwd zolang de URI van het verzoek exact overeenkomt met de opgegeven locatie.
  • ~: De tilde-modifier geeft aan dat de match van het location-blok hoofdlettergevoelig is.
  • ~*: De combinatie van een tilde en een asterisk-modifier geeft aan dat het location-blok hoofdletterongevoelig is bij het zoeken naar een match.
  • ^~: Als de tilde-modifier wordt voorafgegaan door een dakje (caret), zal er geen reguliere expressie-matching plaatsvinden zolang dit blok wordt gekozen als de beste niet-reguliere expressie-match.

Voorbeelden van syntaxis voor location-blokken

Om een voorbeeld van prefix-matching te geven: het location-blok zal worden geselecteerd om te reageren op een URI van een verzoek in de vorm van /site, /site/page1/index.html of /site/index/html:

location site

Voor de doeleinden van deze demonstratie van vereiste URI-matching, zal het blok altijd worden gebruikt om te reageren op URI-verzoeken in de vorm van /page1, en niet op de URI-verzoeken /page1/index.html. Als dit het geselecteerde blok is en het voldoet aan het verzoek met behulp van een indexpagina, zal de daadwerkelijke afhandelaar van het verzoek intern worden omgeleid naar een andere locatie:

Nginx Server

Bijvoorbeeld, een locatie die moet worden geïnterpreteerd met een hoofdlettergevoelige expressie; het volgende blok kan geen verzoeken voor /FLOWER.PNG afhandelen. Het zal echter wel verzoeken voor /tortoise.jpg afhandelen:

Nginx Server and Location Block Selection Algorithms: Overview

Bekijk vervolgens een blok dat hoofdletterongevoelige matching toestaat, vergelijkbaar met het bovenstaande. In dit geval kan het blok zowel //tortoise.jpg als /FLOWER.PNG:

location

De laatste variant is er een waarin een blok voorkomt dat reguliere expressie-matching plaatsvindt als is vastgesteld dat dit de optimale niet-reguliere expressie-match is. Deze kan verzoeken voor /costumes/ninja.html afhandelen:

Nginx Server and Location Block Selection Algorithms: Overview

Kort gezegd bepalen de modifiers de manier waarop location-blokken worden vastgesteld. Dit vertelt ons echter niet wat Nginx gebruikt als beslissingsalgoritme om het location-blok te identificeren waarnaar een verzoek moet worden verzonden. Laten we dat nu bespreken.

Kies de locatie die verzoeken zal afhandelen door Nginx

De methode waarmee Nginx de locatie kiest die een verzoek verwerkt, is vergelijkbaar met hoe serverblokken worden geselecteerd. Met andere woorden, het bepaalt de optimale locatie voor elk verzoek door een proces te doorlopen. Om Nginx nauwkeurig en dienovereenkomstig te configureren, is het absoluut noodzakelijk dat u dit proces begrijpt.

Met de eerder besproken locatiedeclaraties in het achterhoofd, gebruikt Nginx op vergelijkbare wijze potentiële locatiecontexten door de geschiktheid van elke locatie te controleren door deze te vergelijken met de URI van een gegeven verzoek. Hierbij past het de volgende algoritme toe:

  • Eerst controleert Nginx alle locatietypen die geen reguliere expressie bevatten. Dit doet het door te zoeken naar alle op locatie gebaseerde prefix-overeenkomsten. Hiervoor controleert het de locatie tegen de volledige URI van het verzoek.
  • Nginx begint met het zoeken naar een exacte overeenkomst. Zodra een locatieblok dat de = modifier gebruikt is geïdentificeerd, wordt dit vergeleken met het URI-verzoek. Als de twee exact overeenkomen, wordt het locatieblok geselecteerd om het verzoek direct ter plaatse af te handelen.
  • Als er geen locaties zijn die exact overeenkomen met de vergelijking van de = modifier, gaat Nginx over tot het evalueren van prefixes die niet-exact zijn. Zodra het de langste prefixlocatie heeft bepaald die overeenkomt met de URI van het verzoek, zal het de volgende evaluaties uitvoeren:
    • Als de locatie met de langste prefix-overeenkomst de ^~ modifier gebruikt, wordt deze locatie onmiddellijk gekozen.
    • Als de locatie met de langste prefix niet de ^~ modifier gebruikt, wordt de overeenkomst kortstondig door Nginx onthouden om de focus van de zoekopdracht te laten verschuiven.
  • Zodra de langste prefixlocatie-overeenkomst is gevonden en opgeslagen, schakelt Nginx over naar de evaluatie van locaties met reguliere expressies. Deze omvatten zowel hoofdlettergevoelige als hoofdletterongevoelige overeenkomsten. Als de langst overeenkomende prefixlocatie reguliere locaties in zich heeft, zal Nginx de lijst herstructureren om deze bovenaan de lijst met locaties te plaatsen. De eerste expressie uit de hergesorteerde lijst die overeenkomt met de URI van een verzoek, is de locatie die wordt gekozen om het verzoek te bedienen.
  • Als er geen reguliere expressies worden gevonden die aan de verzoek-RI voldoen, wordt de eerder opgeslagen locatie gekozen om het verzoek te verwerken.

Nginx geeft standaard prioriteit aan overeenkomsten met reguliere expressies boven preferentiële prefix-overeenkomsten. Het evalueert echter wel eerst prefixlocaties, zodat de beheerder deze neiging kan herroepen met de = en ^~ modifiers.

Een ander belangrijk aandachtspunt is dat hoewel prefixlocaties doorgaans gebaseerd zijn op de meest specifieke, langst gevonden overeenkomst, een controle van een reguliere expressie stopt zodra de eerste overeenkomst is geïdentificeerd. Dit betekent dat de positionering binnen de configuratie reële gevolgen heeft voor locaties met reguliere expressies.

Een laatste punt om te bespreken is dat de overeenkomsten met reguliere expressies binnen de overeenkomst met de langste prefix in wezen voorrang krijgen tijdens de locatie-evaluaties van Nginx. Deze worden bovenaan de lijst geplaatst en vóór andere reguliere expressies geëvalueerd.

Wanneer vindt het overspringen naar andere locaties plaats bij de evaluatie van locatieblokken?

Gewoonlijk wordt een verzoek, zodra het is beoordeeld en er een locatieblok is geselecteerd om het af te handelen, volledig binnen die context afgehandeld. Dit betekent dat alleen de overgeërfde richtlijnen en geselecteerde locaties bepalend zijn voor de verwerking van het verzoek, zonder enige input van nevengeschikte locatieblokken.

Hoewel dit een algemene richtlijn is die een voorspelbaar ontwerp van locatieblokken mogelijk maakt, kunnen soms bepaalde richtlijnen binnen de locatie ook een nieuwe zoekopdracht activeren. Met andere woorden, de regel van 'slechts één locatieblok' kent een paar uitzonderingen. Die uitzonderingen komen mogelijk niet overeen met de verwachting van de locatieblokken. Daarom behandelen ze het verzoek mogelijk niet zoals verwacht.

Deze interne omleidingen kunnen zich manifesteren als gevolg van bepaalde richtlijnen, waaronder:

  • index
  • rewrite
  • error_page
  • try_files

Als u de index-richtlijn gebruikt, zal dit tijdens de verwerking van het verzoek altijd leiden tot een interne redirect. Hoewel het vinden van locatie-overeenkomsten doorgaans de uitvoering van het algoritme beëindigt om het selectieproces te versnellen, zal het verzoek, als de gevonden locatie-overeenkomst een directory is, waarschijnlijk worden omgeleid naar een andere locatie om formeel te worden verwerkt.

Bijvoorbeeld, de volgende eerste locatie komt overeen met een verzoek-URI van /exact. Om het verzoek te verwerken, stuurt de index-richtlijn die het locatieblok overerft het verzoek echter door naar een secundair blok:

index

Voor dat scenario, als de uitvoering binnen het primaire blok moet blijven, zal een ander schema het verzoek naar de directory moeten verwerken. Een manier om dit te doen is door een ongeldige index in te stellen voor het betreffende blok en in plaats daarvan auto-index te activeren:

location exact

Hoewel deze methode in een paar gevallen kan werken, is deze in de meeste contexten over het algemeen niet praktisch toepasbaar. Een exacte directory-overeenkomst kan nuttig zijn voor situaties waarin het verzoek moet worden herschreven. Dit zal een gloednieuwe locatiezoekopdracht activeren.

Een andere richtlijn die kan worden gebruikt om de verwerkingslocatie opnieuw te evalueren, is de try_files-richtlijn. Deze vertelt Nginx om specifiek te controleren of een benoemde set bestanden of mappen bestaat, waarbij het laatste zoekcriterium de URI is waarnaar Nginx intern moet omleiden.

Laten we eens nadenken over de volgende configuratie:

root var

Als er een verzoek is voor /blahblah, zal de eerste locatie dit ontvangen. Als het bestand blahblah niet wordt gevonden in de directory /var/www/main, zal dit een vervolgzoekopdracht naar blahblah.html activeren. Vervolgens zal er worden gezocht naar een subdirectory met de naam blahblah in de directory /var/www/main. Als al die controles mislukken, zal het omleiden naar /fallback/index.html. Dit zal een nieuwe locatiezoekopdracht activeren die door een ander locatieblok zal worden opgepikt. Vervolgens zal het bestand /var/www/another/fallback/index.html worden verwerkt.

Een andere richtlijn die resulteert in een redirect naar een ander locatieblok is de rewrite-richtlijn. Nginx zal zoeken naar een nieuwe overeenkomstige locatie op basis van het resultaat van de rewrite-richtlijn wanneer de 'last'-parameter wordt gebruikt. Als het laatste voorbeeld wordt gewijzigd om nu deze rewrite-richtlijn op te nemen, wordt het duidelijk dat het verzoek kan worden omgeleid naar een andere locatie zonder dat de try_files-richtlijn wordt geïmplementeerd:

root var ww main

Voor dit voorbeeld zal het verzoek om /rewrite/hello in eerste instantie door de eerste locatie worden afgehandeld. Nadat het is herschreven naar /hello, zal een secundaire locatiezoekopdracht worden geactiveerd. Deze zal overeenkomen met de eerste locatie. Het zal worden verwerkt door de try_file-richtlijn, wat mogelijk terugvalt op /fallback/index.html als het geen resultaten oplevert.

Als er echter een verzoek wordt gedaan voor /rewrite/fallback/hello, zal er een overeenkomst met het eerste blok worden gevonden. De rewrite zal dus opnieuw worden verwerkt, maar dit keer met /fallback/hello als resultaat. Het verzoek zal op een ander locatieblok worden verwerkt.

Vergelijkbare situaties doen zich voor wanneer u de return-richtlijn gebruikt om statuscodes 301 of 302 te verzenden. Het enige verschil is dat er een nieuw verzoek ontstaat, wat zich manifesteert in een zeer duidelijke redirect. Dit kan zich op vergelijkbare wijze voordoen met de rewrite-richtlijn wanneer u de vlaggen 'permanent' of 'redirect' toepast.

Een andere richtlijn die kan leiden tot vergelijkbare interne redirects als die van try_again is de error_page-richtlijn. U kunt deze gebruiken wanneer u specifieke foutcodes tegenkomt bij de verwerking. Wanneer een try_files-richtlijn is ingesteld, zal de error_page-richtlijn waarschijnlijk nooit worden uitgevoerd. Dat’s omdat die richtlijn de volledige levenscyclus van het verzoek zal afhandelen.

Laten we het volgende voorbeeld bekijken:

root screenshot

In dit geval zal elk verzoek worden verwerkt door het eerste blok dat bestanden serveert vanuit /var/www/main. Dit geldt niet voor de verzoeken die beginnen met /another. Maar als een bestand niet wordt gevonden, zal er een interne redirect worden gestart naar /another/whoops/html. Dit zal leiden tot een nieuwe locatiezoekopdracht. Op zijn beurt zal dit het verzoek naar een secundair blok leiden, waarbij dat bestand wordt aangesproken vanuit /var/www/another/whoops.html.

Zoals blijkt, kan inzicht in situaties waarin Nginx een nieuwe locatiezoekopdracht activeert, helpen om het systeemgedrag beter te voorspellen wanneer verzoeken worden verwerkt.

Conclusie

Het werk van beheerders wordt aanzienlijk eenvoudiger wanneer ze de methoden begrijpen waarmee Nginx clientverzoeken afhandelt. Dit stelt beheerders in staat om vast te stellen naar welk serverblok het verzoek zal gaan. Ze kunnen ook bepalen welk locatieblok zal worden geselecteerd op basis van de verzoek-URI. Over het algemeen biedt het beheerders ook de mogelijkheid om de door Nginx toegepaste contexten te traceren bij het afhandelen van elk verzoek.

Tot slot kun je een kijkje nemen bij de andere handleidingen op onze blog die gericht zijn op Nginx. Ze zullen je helpen om beter te profiteren van een van de meest populaire webservers ter wereld:

Veel computerplezier!

author

Manpreet Singh

Auteur · CloudSigma

Preslav Dobrev is een creatief ontwerper bij CloudSigma, met de nadruk op een consistente bedrijfsidentiteit door middel van traditionele en innovatieve marketingkanalen. Hij is bedreven in het samenvoegen van artistieke visie met strategische marketing om impactvolle merkverhalen te creëren.

Reacties

Nog geen reacties. Wees de eerste.