Uvod
Nginx je među najpopularnijim opcijama web poslužitelja na svijetu. Sposoban je uspješno se nositi s mnoštvom istovremenih veza klijenata. Istovremeno funkcionira kao poslužitelj e-pošte, web poslužitelj ili reverzni proxy poslužitelj.
Ovaj vodič ima za cilj ocrtati metode iza kulisa koje usmjeravaju kako Nginx obrađuje zahtjeve klijenata. Demistificirat ćemo server i location blok dizajn, kao i objasniti kako najbolje smanjiti prividnu nepredvidivost rukovanja zahtjevima.
Prije svega, evo sveobuhvatnog vodiča o tome kako instalirati Nginx na vaš Ubuntu poslužitelj. A sada, počnimo!
Konfiguracija blokova s Nginxom
Nginxov logički pristup uključuje razvrstavanje konfiguracija namijenjenih različitim svrhama u zasebne, logičnije blokove sadržaja. Oni će se nalaziti u hijerarhijskoj strukturi. Kada klijent uputi zahtjev, Nginx pokreće proces kojim utvrđuje koji su od ovih konfiguracijskih blokova najprikladniji za rješavanje tog zahtjeva. Usredotočit ćemo se na ovaj proces donošenja odluka.
Primarni blokovi o kojima raspravljamo bit će server blokovi i location blokovi. Server blokovi su podskup konfiguracija koje Nginx uspostavlja, a koje definiraju koji će virtualni poslužitelj biti odgovoran za rukovanje definiranom vrstom zahtjeva. Najčešće se temelje na IP adresi, nazivu domene ili portu dolaznog zahtjeva. Administratori konfiguriraju više server blokova. Zatim moraju odlučiti koja bi od veza trebala rukovati zahtjevom.
Location blokovi nalaze se unutar server blokova. Oni donose odluke o tome kako i koje resurse možete iskoristiti za rukovanje dolaznim zahtjevima prema njihovom matičnom poslužitelju. Ovaj model je vrlo fleksibilan. URI prostor se može konfigurirati za korištenje ovih blokova na način koji administrator smatra najboljim.
Odlučite koji će blok rukovati kojim zahtjevom uz Nginx
Nginx dopušta definiranje više server blokova. Svi oni funkcioniraju kao različiti virtualni web poslužitelji. Stoga mora postojati metoda koja određuje koji će poslužitelj odgovoriti na određene dolazne zahtjeve. To se postiže pronalaženjem najboljeg rješenja za izvedbu zahtjeva kroz sustav definiranih provjera.
Nginx se prvenstveno bavi dvjema glavnim direktivama server bloka: listen i server_name.
Pronađite moguća podudaranja s direktivom 'Listen'
Prvo što Nginx procjenjuje su port i IP adresa zahtjeva. Zatim ih uspoređuje s direktivom listen svakog poslužitelja. Ovo raščlanjivanje popisa poslužitelja pomaže u izolaciji samo onih server blokova koji mogu riješiti dotični zahtjev.
Obično će direktiva listen definirati port i IP adresu na koje će određeni server blok biti odgovoran za odgovaranje. Server blok koji nema direktivu listen prema zadanim postavkama prima parametre listen na 0.0.0.0:80. Ako Nginx pokreće običan korisnik koji nije root, parametar listen definiran je kao 0.0.0.0:8080. To znači da bez obzira na sučelje, ako blokovi dolaze s porta 80, blokovi definirani na taj način će odgovoriti na njih. Međutim, ova zadana vrijednost nema veliku težinu u procesu odabira poslužitelja.
Direktivu listen možete konfigurirati na:
- Samostalnu IP adresu koja sluša zahtjeve na zadanom portu (80).
- Samostalni port koji sluša bilo koje sučelje na tom portu.
- Kombinaciju porta i IP adrese.
- Zadanu putanju Unix utičnice (ova opcija ima utjecaja samo kada zahtjevi prolaze kroz različite poslužitelje).
Nginx će primijeniti skup pravila pri odlučivanju kojem će server bloku biti poslan zahtjev. Pravila ovise o specifičnoj konfiguraciji direktive listen. Ona su sljedeća:
- Ako je direktiva listen nepotpuna, dijelovi koji nedostaju dobivaju svoje zadane vrijednosti. To znači da će IP adresa i port biti prisilno popunjeni zadanim vrijednostima kako bi se zahtjev obradio.
- U ovom slučaju, blok koji ne sadrži direktivu listen koristit će zadanu vrijednost 0.0.0.0:80.
- Blok kojem nedostaje port, a ima IP adresu 111.111.111.111 postat će 111.111.111.111:80.
- Kada nema IP adrese, blok s portom 8888 preuzet će zadanu IP adresu koja će se pridodati kako bi se stvorilo 0.0.0.0:8888.
- Nakon što odredi IP adresu i port, Nginx će potražiti server blokove koji se nude kao podudaranje za taj port.
- Ako pronađe samo jedno specifično podudaranje, to će biti taj server blok. Ako postoji više blokova koji ispunjavaju uvjete, Nginx će se okrenuti direktivi server_name kako bi dodatno suzio izbor na točan server blok o kojem je riječ.
Nginx će pribjeći evaluaciji direktive server_name samo ako nije pronašao server blok s točnom razinom specifičnosti iz direktive listen. Ako je example.com na portu 80, s IP adresom 192.168.1.10, prvi blok u ovom primjeru uvijek će biti onaj koji prihvaća zahtjev. To je slučaj bez obzira na to što kaže direktiva server_name:

Ako postoji više od samo jednog kvalificiranog server bloka s podudaranjem specifičnosti, tada će se uzeti u obzir direktiva server_name.
Pronađite moguća podudaranja s direktivom ‘Server_Name’
Ako su direktive listen jednako specifične, Nginx će provjeriti zaglavlje ‘Host’ zahtjeva. To je vrijednost koja će sadržavati IP ili domenu koju je klijent prvotno želio dosegnuti. Nginx će koristiti direktivu server_name unutar svakog još uvijek kvalificiranog kandidata za server blok. Ove evaluacije provodi na temelju formule. Ona je sljedeća:
- Prvi pokušaj Nginxa bit će identificirati blok s vrijednošću server_name koja točno odgovara vrijednosti zaglavlja ‘Host’ u zahtjevu. Ako ga pronađe, blok koji sadrži točno podudaranje bit će onaj koji poslužuje zahtjev. U slučaju da pronađe više blokova, odabrat će prvi na popisu.
- Ako nema točnih podudaranja, Nginx će zatim pokušati upotrijebiti server_name kako bi pronašao server blok koji se podudara uz upotrebu *, zamjenskog znaka na početku naziva server bloka u konfiguraciji. Pronalaženje bloka ovom metodom znači da je server blok određen. Ako pronađe više od jednog podudaranja, najduže podudaranje bit će ono koje će ispuniti zahtjev.
- Bez podudarajućeg zamjenskog znaka, Nginx će pokušati pronaći server blok s podudarajućim zamjenskim znakom na kraju. Drugim riječima, to će biti naziv poslužitelja s * u konfiguraciji. Ako se takav pronađe, koristi se za zahtjev. Dok, ako ih pronađete više, Nginx će ponovno upotrijebiti najduže podudaranje.
- U slučaju da i dalje nema podudaranja nakon oba pokušaja sa zamjenskim znakovima, Nginx će procijeniti one server blokove koji definiraju server_name pomoću regularnih izraza (označenih s ~ ispred naziva). Prva instanca server_name s izrazom koji odgovara onom iz zaglavlja ‘Host’, smatrat će se server blokom za obradu zahtjeva.
- Ako u ovom trenutku i dalje nema podudaranja, Nginx će koristiti zadani server blok za tu kombinaciju porta i IP adrese.
Svaka kombinacija porta/IP adrese imat će dodijeljeni server blok. On će se koristiti ako su pravila za određivanje odgovarajućeg server bloka za obradu zahtjeva bezuspješna. To će biti prvi blok u konfiguraciji koji sadrži opciju default_server u direktivi listen (to bi nadjačalo početno pronađeni algoritam). Svaka kombinacija IP adrese/porta može imati najviše jednu postavku default_server.
Primjeri odabira server bloka
Ako definirani server_name točno odgovara vrijednosti zaglavlja ‘Host’, to će biti server blok odabran za obradu zahtjeva. Sljedeći primjer prikazuje zaglavlje ‘Host’ zahtjeva označeno kao “host1.example.com”. U ovom slučaju odabrat će se drugi poslužitelj:

Bez točnog podudaranja, Nginx će provjeriti postoji li server_name sa zamjenskim znakom. Ako ne postoji, odabrat će se najduže podudaranje koje počinje sa zamjenskim znakom. U nastavku, “www.example.org” nalazi se u zaglavlju “Host”. To znači da će odabrati drugi blok:

Bez podudaranja koje počinje s džoker znakom, Nginx prelazi na provjeru završnog džoker znaka. Najduže podudaranje koje završava s džoker znakom bit će odabrano za obradu zahtjeva. U ovom slučaju, zaglavlje “Host” je “www.example.com”, pa će odabrati treći server blok:

Ako i dalje nema podudaranja, Nginx će pokušati uskladiti direktive server_name pomoću standardnih izraza. Prvi od tih izraza odabire se za obradu zahtjeva. Ako je “Host” “www.example.com,” drugi server blok bit će odabran za obradu zahtjeva:

Ako i dalje nema podudaranja, zahtjev će ići na kombinaciju IP adrese i porta s konfiguriranim odgovarajućim zadanim poslužiteljem.
Podudaranje location blokova
Nginx također mora uspostaviti algoritam pomoću kojeg će odlučiti koji će location blok na poslužitelju biti odgovoran za odgovaranje na zahtjev.
Sintaksa za location blokove
Prije nego što objasnimo kako Nginx odlučuje koji će location blok obraditi zahtjeve, pregledat ćemo sintaksu u definicijama location blokova. Kao što je ranije navedeno, location blokovi nalaze se unutar server blokova (i drugih location blokova). Njihova je svrha donošenje odluka o tome kako obraditi URI zahtjeva. URI je dio zahtjeva koji dolazi nakon IP adrese i porta ili naziva domene u zahtjevu.
Location blokovi obično izgledaju ovako:

Nginx će provjeriti URI zahtjeva u odnosu na location_match. Prisutnost ili odsutnost gore navedenog modifikatora odredit će način na koji će Nginx pokušati uskladiti blokove. Ovisno o modifikatoru, location blokovi tumačit će se prema sljedećim pravilima:
- Bez modifikatora: Bez ikakvih modifikatora, lokacija će se tumačiti kao podudaranje prefiksa. To znači da će se navedena lokacija uspoređivati s početkom URI-ja u zahtjevu kako bi se utvrdilo ispravno podudaranje.
- =: Znak jednakosti označava da će se ovaj blok smatrati podudaranjem sve dok se URI zahtjeva točno podudara s navedenom lokacijom.
- ~: Modifikator tilde označava da će podudaranje location bloka biti osjetljivo na velika i mala slova.
- ~*: Kombinacija tilde i zvjezdice označava da location blok neće biti osjetljiv na velika i mala slova prilikom traženja podudaranja.
- ^~: Ako se ispred modifikatora tilde nalazi kapa, podudaranje regularnih izraza neće se dogoditi sve dok je ovaj blok odabran kao najbolje podudaranje koje nije regularni izraz.
Primjeri sintakse location blokova
Kako bismo prikazali primjer podudaranja prefiksa, location blok bit će odabran za odgovor na URI zahtjeva u obliku /site, /site/page1/index.html ili /site/index/html:

Za potrebe ove demonstracije potrebnog podudaranja URI-ja, blok će se uvijek koristiti za odgovaranje na URI zahtjeve u obliku /page1, a ne na URI zahtjev /page1/index.html. Ako je ovo odabrani blok i on ispunjava zahtjev pomoću indeksne stranice, stvarni rukovatelj zahtjeva bit će interno preusmjeren na drugu lokaciju:

Na primjer, za lokaciju koja se mora tumačiti izrazom osjetljivim na velika i mala slova, sljedeći blok ne bi mogao obraditi zahtjeve za /FLOWER.PNG. Međutim, obradit će zahtjeve za /tortoise.jpg:

Zatim promotrite blok koji bi dopustio podudaranje neosjetljivo na velika i mala slova, slično onome gore. U ovom slučaju, blok bi mogao obraditi i //tortoise.jpg i /FLOWER.PNG:

Posljednja varijanta je ona u kojoj bi blok spriječio podudaranje regularnih izraza ako se utvrdi da je to optimalno podudaranje koje nije regularni izraz. Ovaj blok može obraditi zahtjeve za /costumes/ninja.html:

Da budemo precizniji, modifikatori određuju način na koji se definiraju location blokovi. To nam, međutim, ne govori što Nginx koristi kao algoritam za donošenje odluka kako bi identificirao location blok u koji se zahtjev treba poslati. Pozabavimo se time u nastavku.
Odabir lokacije koja će obrađivati zahtjeve u Nginxu
Metoda kojom Nginx odabire lokaciju koja obrađuje zahtjev slična je načinu na koji se odabiru blokovi poslužitelja. Drugim riječima, on određuje optimalnu lokaciju za svaki zahtjev prolazeći kroz proces. Kako biste konfigurirali Nginx točno i u skladu s tim, imperativ je da razumijete ovaj proces.
Imajući na umu ranije spomenute deklaracije lokacija, Nginx na sličan način koristi potencijalne kontekste lokacija provjeravajući kvalifikaciju za svaku lokaciju uspoređujući s njom URI iz danog zahtjeva. Pri tome primjenjuje sljedeći algoritam:
- Prvo, Nginx provjerava sve vrste lokacija koje ne uključuju regularni izraz. To čini tražeći sva podudaranja prefiksa temeljena na lokaciji. Da bi to učinio, provjerava lokaciju u odnosu na potpuni URI zahtjeva.
- Nginx počinje tražiti točno podudaranje. Nakon što se identificira blok lokacije koji koristi modifikator =, on se uspoređuje s URI-jem zahtjeva. Ako se to dvoje točno podudara, blok lokacije se odabire za obradu zahtjeva odmah na licu mjesta.
- Ako nema lokacija koje točno odgovaraju usporedbi s modifikatorom =, Nginx nastavlja s procjenom prefiksa koji nisu točni. Nakon što odredi lokaciju s najdužim prefiksom koja odgovara URI-ju zahtjeva, izvršit će sljedeće procjene:
- Ako lokacija s najdužim podudaranjem prefiksa koristi modifikator ^~, ova će lokacija odmah biti odabrana.
- Ako lokacija s najdužim prefiksom ne koristi modifikator ^~, Nginx nakratko zadržava podudaranje kako bi se fokus pretraživanja mogao preusmjeriti.
- Nakon što se pronađe i pohrani podudaranje lokacije s najdužim prefiksom, Nginx prelazi na procjenu lokacija s regularnim izrazima. To uključuje podudaranja osjetljiva i neosjetljiva na velika i mala slova. Ako najduža podudarajuća lokacija prefiksa sadrži bilo kakve regularne lokacije unutar sebe, Nginx će preoblikovati popis kako bi ih postavio blizu vrha popisa lokacija. Prvi izraz iz ponovno razvrstanog popisa koji odgovara URI-ju zahtjeva bit će lokacija odabrana za posluživanje zahtjeva.
- Ako se ne pronađu regularni izrazi koji bi zadovoljili RI zahtjeva, za obradu zahtjeva odabrat će se prethodno pohranjena lokacija.
Nginx prema zadanim postavkama daje prednost podudaranjima regularnih izraza u odnosu na ona s preferencijalnim prefiksom. Međutim, on prvo procjenjuje lokacije prefiksa, tako da administratorski dio može nadjačati ovu tendenciju s modifikatorima = i ^~.
Još jedan važan zaključak je da, iako se lokacije prefiksa obično temelje na najspecifičnijem, najdužem pronađenom podudaranju, provjera regularnog izraza zaustavlja se čim se identificira prvo podudaranje. To znači da pozicioniranje unutar konfiguracije ima stvarne implikacije na lokacije regularnih izraza.
Posljednja točka koju treba spomenuti jest da će podudaranja regularnih izraza unutar podudaranja s najdužim prefiksom u biti preskočiti red tijekom Nginxovih procjena lokacija. Ona će biti postavljena na vrh popisa i procijenjena prije ostalih regularnih izraza.
Kada dolazi do skakanja na druge lokacije u procjenama blokova lokacija?
Obično, nakon što se zahtjev procijeni i odabere blok lokacije za njegovo rukovanje, on će se u potpunosti rješavati unutar tog konteksta. To znači da su samo naslijeđene direktive i odabrane lokacije determinante u obradi zahtjeva, bez ikakvog utjecaja susjednih blokova lokacija.
Iako je ovo opća direktiva koja omogućuje predvidljiv dizajn blokova lokacija, ponekad određene direktive unutar lokacije mogu pokrenuti i novu pretragu. Drugim riječima, pravilo 'samo jednog bloka lokacije' ima nekoliko iznimaka. Te se iznimke možda neće podudarati s očekivanjima blokova lokacija. Stoga možda neće riješiti zahtjev na očekivani način.
Ova interna preusmjeravanja mogu se manifestirati zbog nekih direktiva uključujući:
- index
- rewrite
- error_page
- try_files
Ako koristite direktivu index, to će uvijek rezultirati internim preusmjeravanjem tijekom obrade zahtjeva. Iako pronalaženje podudaranja lokacije obično završava izvršavanje algoritma kako bi se ubrzao proces odabira, ako je pronađeno podudaranje lokacije direktorij, zahtjev će vjerojatno biti preusmjeren na drugu lokaciju kako bi se formalno obradio.
Na primjer, sljedeća prva lokacija podudara se sa zahtjevom URI-ja /exact. Međutim, za obradu zahtjeva, direktiva index koju blok lokacije nasljeđuje preusmjerava zahtjev u sekundarni blok:

Za taj scenarij, ako izvršavanje mora ostati unutar primarnog bloka, druga shema morat će obraditi zahtjev prema direktoriju. Jedan od načina da se to učini jest postavljanje nevažećeg indeksa za dotični blok i aktiviranje auto indexa umjesto toga:

Iako ova metoda može funkcionirati u nekoliko slučajeva, uglavnom nije praktički primjenjiva u većini konteksta. Točno podudaranje direktorija može biti korisno u situacijama kada je zahtjev potrebno ponovno zapisati. To će pokrenuti potpuno novu pretragu lokacije.
Druga direktiva koja se može koristiti za ponovnu procjenu lokacije obrade je direktiva try_files. Ona govori Nginxu da specifično provjeri postoji li imenovani skup datoteka ili direktorija, pri čemu je posljednji kriterij pretraživanja URI na koji Nginx treba interno preusmjeriti.
Razmotrimo sljedeću konfiguraciju:

Ako postoji zahtjev za /blahblah, prva lokacija će ga primiti. Ako se datoteka blahblah ne pronađe u direktoriju /var/www/main, to će pokrenuti naknadnu pretragu za blahblah.html. Zatim će tražiti poddirektorij pod nazivom blahblah u direktoriju /var/www/main. Ako sve te provjere ne uspiju, preusmjerit će na /fallback/index.html. To će pokrenuti još jednu pretragu lokacije koju će preuzeti drugi blok lokacije. Zatim će obraditi datoteku /var/www/another/fallback/index.html.
Druga direktiva koja rezultira preusmjeravanjem na drugi blok lokacije je direktiva rewrite. Nginx će tražiti novu podudarajuću lokaciju na temelju rezultata direktive rewrite kada se koristi parametar last. Ako se posljednji primjer izmijeni tako da sada uključuje ovu direktivu rewrite, postaje očito da se zahtjev može preusmjeriti na drugu lokaciju bez implementacije direktive try_files:

Za ovaj primjer, zahtjev za /rewrite/hello u početku će riješiti prva lokacija. Nakon što se ponovno zapiše u /hello, pokrenut će se sekundarna pretraga lokacije. Podudarat će se s prvom lokacijom. Obradit će ga direktiva try_file, potencijalno se vraćajući na /fallback/index.html ako ne dade nikakve rezultate.
Međutim, ako se uputi zahtjev za /rewrite/fallback/hello, pronaći će se podudaranje s prvim blokom. Stoga će se rewrite ponovno obraditi, ali ovaj put će kao rezultat dati /fallback/hello. Zahtjev će se obraditi na drugom bloku lokacije.
Slične situacije se događaju kada koristite direktivu return za slanje statusnih kodova 301 ili 302. Jedina razlika je u tome što to rezultira novim zahtjevom i manifestira se u vrlo očiglednom preusmjeravanju. Slično tome, to se može dogoditi s direktivom rewrite kada primijenite zastavice permanent ili redirect.
Druga direktiva koja može dovesti do sličnih internih preusmjeravanja kao i try_again je direktiva error_page. To možete koristiti kada naiđete na određene kodove pogrešaka u obradi. Kada je postavljena direktiva try_files, direktiva error_page se vjerojatno nikada neće izvršiti. To je’ zato što će ta direktiva upravljati punim životnim ciklusom zahtjeva.
Razmotrimo sljedeći primjer:

U ovom slučaju, svaki zahtjev će obraditi prvi blok koji poslužuje datoteke iz /var/www/main. To se ne odnosi na one zahtjeve koji počinju s /another. Ali ako datoteka ne bude pronađena, pokrenut će se interno preusmjeravanje na /another/whoops/html. To će dovesti do još jedne pretrage lokacije. To će pak usmjeriti zahtjev na sekundarni blok, pri čemu će se ta datoteka adresirati iz /var/www/another/whoops.html.
Kao što je vidljivo, razumijevanje situacija u kojima će Nginx pokrenuti novu pretragu lokacije može pomoći u boljem predviđanju ponašanja sustava prilikom obrade zahtjeva.
Zaključak
Posao administratora postaje neizmjerno jednostavniji kada razumiju metode kojima Nginx rješava zahtjeve klijenata. To administratorima omogućuje da utvrde u koji će blok poslužitelja zahtjev otići. Također mogu odrediti blok lokacije koji će biti odabran na temelju URI-ja zahtjeva. Uglavnom, to administratorima također pruža mogućnost praćenja primijenjenih Nginx konteksta prilikom rješavanja svakog zahtjeva.
Naposljetku, možete pogledati i ostale vodiče na našem blogu koji se fokusiraju na Nginx. Oni će vam pomoći da bolje iskoristite prednosti jednog od najpopularnijih web poslužitelja na svijetu:
- Svijet web poslužitelja: Apache vs. Nginx
- Kako osigurati Nginx s Let’s Encrypt na Ubuntu 20.04
- Automatizirajte obnove LetsEncrypt SSL certifikata za Nginx
- Postavljanje Laravela, Nginxa i MySQL-a s Docker Compose
Ugodan rad!
Komentari
Još nema komentara. Budite prvi.