Optimizacija NGINX-a za bolje performanse web servera
NGINX je jedan od najpopularnijih open-source web servera na tržištu, pre svega zahvaljujući tome što se pokazao kao izuzetno fleksibilan i efikasan. Pored toga što se može koristiti kao klasičan web server, možete ga koristiti i za distribuiranje opterećenja (load balancing), različite modele keširanja, kompresiju sadržaja, kao i za brojne druge funkcionalnosti koje olakšavaju rad čak i najzahtevnijih web aplikacija.
Ipak, da biste izvukli maksimum iz svog NGINX web servera, biće neophodno da uradite i neka dodatna podešavanja, kao i optimizaciju servera. Zato ćemo vam u ovom tekstu dati neke savete za podešavanje, kao i za finu optimizaciju NGINX web servera.
Zašto je optimizacija NGINX-a važna?
Optimizacija NGINX-a je važna kako bi vaš web sajt mogao da radi brže i pouzdanije. Kada je sve dobro podešeno i optimizovano, NGINX web server može da obradi više istovremenih zahteva, a da to previše ne utiče na opterećenje resursa. Na taj način se smanjuje vreme čekanja, što znači da će posetioci imati bolje korisničko iskustvo na vašem sajtu.
Pored toga, dobro optimizovan NGINX lakše podnosi iznenadne skokove u posećenosti vašeg web sajta, što znači da će vaš sajt stabilnije raditi ukoliko dođe do veće posećenosti.
Ukoliko želite da saznate kako da pripremite svoj web sajt veću posećenost, predlažemo da pročitate Kako da svoj cloud server pripremite za Black Friday i Cyber Monday.
Ali, hajde da pre svega vidimo kako da optimizujete NGINX server.
Početna analiza i priprema
Kao i uvek, pre bilo kakvog podešavanja, poželjno je da uradite detaljnu analizu trenutnog stanja sistema i aplikacije.
Praćenje iskorišćenosti sistemskih resursa
Praćenje potrošnje resursa je jedna od najvažnijih aktivnosti koju je potrebno da radite kada je u pitanju web server. Jedan od najboljih alata koje preporučujemo za detaljan uvid u to kako i koliko su vaši resursi opterećeni, je alat pod nazivom Dotcom-Monitor. U jednom od naših prethodnih tekstova smo detaljno predstavili ovaj alat, pa ukoliko želite da ga detaljnije upoznate, preporučujemo da pročitate Dotcom-Monitor – alat za monitoring web aplikacija, web servera i mrežnih resursa.
Na primer, ako prilikom monitoringa primetite da CPU skače na 100% u određenim intervalima, to znači da je verovatno potrebno da dodatno prilagodite broj worker procesa u NGINX-u, ili eventualno razmotrite unapređivanje hardvera.
Uvid u vrstu i veličinu sadržaja
Ako je većina sadržaja na vašem web sajtu statička (HTML, CSS, slike, JavaScript), optimizacija keširanja i kompresije može da bude dobra strategija za ubrzanje rada vašeg sajta.
S druge strane, ako je reč o kompleksnim API pozivima i dinamičkom sadržaju, bolja opcija je da razmislite o FastCGI keširanju (za PHP, Python, itd.) ili da smanjite obradu na nivou aplikacije.
Takođe, važno je da proverite koje su prosečne veličine fajlova na vašem sajtu i koliko često se menjaju. To direktno utiče na odluke o implementaciji cache-control zaglavlja i rasporedu invalidacije keša.
Provera latencije i propusnosti
Alati kao što je Dotcom-Monitor vam omogućavaju i da generišete veliki broj paralelnih zahteva ka NGINX-u i merite vreme odziva, protok, kao i eventualne greške.
Ovo je korisno kada želite da testirate granice i uočite uska grla – na primer, da li je CPU taj koji postaje preopterećen, ili se radi o sporom pristupu disku, bazi podataka ili spoljašnjim servisima.
Sa rezultatima ovakvih testiranja možete eksperimentalno menjati NGINX parametre (poput worker_processes ili worker_connections) i pratiti kako se menja latencija u odnosu na različito opterećenje.
Analiza NGINX logova
NGINX beleži svoje aktivnosti u logu (access log), gde se nalaze informacije o svakom zahtevu, uključujući HTTP metode, rute, statuse, veličinu odgovora i IP adrese klijenata.
Takođe beleži i greške (error log), koje mogu da ukažu na neispravnu konfiguraciju, mrežne probleme ili preopterećene proksije.
Povremena analiza ovih logova pomaže u otkrivanju trendova, kao što su nagli rast 4xx ili 5xx status kodova, što može da ukaže na probleme u aplikaciji, bazi ili NGINX konfiguraciji.
Pokazalo se kao dobra praksa i periodično rotiranje logova (log rotation), kako bi se izbegla pretrpanost diska i lakše pratila istoriju.
Analiza web aplikacije
Ukoliko NGINX koristite kao reverzni proksi, vaše web okruženje može imati više slojeva: različite aplikacione servere, mikroservise, baze podataka ili čak udaljene API-je na koje se oslanjate. Svaki od tih slojeva može povećati latenciju, pa je važno da identifikujete gde tačno nastaju uska grla.
Na primer, ako se vaša aplikacija sastoji od desetak mikroservisa koji komuniciraju međusobno, može da dođe do kumulativnog kašnjenja čak i ako je NGINX savršeno optimizovan. U ovakvim situacijama, pored finog podešavanja NGINX-a, treba voditi računa i o mrežnoj infrastrukturi, dostupnosti i kapacitetu drugih servisa, kao i o načinu na koji klijentska strana upravlja (ili ponovo koristi) ostvarene konekcije.
Obratite pažnju i na sigurnosne mehanizme kao što su SELinux ili AppArmor, jer i oni imaju izvestan uticaj na performanse. Ovi mehanizmi pružaju dodatni nivo zaštite, ograničavajući pristup NGINX-u kritičnim delovima sistema i prateći svaku operaciju.
Ovakav pristup poboljšava bezbednost, ali može donekle usporiti rad servera, naročito pri velikom obimu saobraćaja. Zbog toga je važno testirati NGINX i sa uključenim i sa isključenim zaštitama, kako biste našli najbolji odnos između sigurnosti i performansi.
Takođe, treba odlučiti koji HTTP protokol ćete koristiti (HTTP 1.1, HTTP/2, HTTP/3), budući da napredniji protokoli mogu značajno poboljšati brzinu učitavanja resursa Dok je HTTP 1.1 i dalje rasprostranjen, HTTP/2 i HTTP/3 su koncipirani tako da smanje broj dodatnih round-trip zahteva i omoguće efikasniji prenos podataka. Na taj način, moderniji protokoli mogu doneti uočljivo brže učitavanje stranica i ukupno bolje korisničko iskustvo, pod uslovom da ih i klijentska strana (pregledači ili aplikacije) adekvatno podržavaju.
Koraci za optimizaciju NGINX servera
Podešavanje worker procesa
NGINX koristi efikasan event-based model obrade zahteva, a ključan deo tog modela su tzv. worker procesi. Podrazumevano, NGINX obično pokreće onoliko radnih procesa koliko imate CPU jezgara u sistemu, što je dobro polazište. Međutim, ponekad je potrebno povećati ili smanjiti broj worker procesa kako biste izvukli maksimum.
Na primer, ako NGINX obrađuje mnogo malih i kratkotrajnih zahteva, a vi posedujete moderni CPU sa brojnim jezgrima, može se ispostaviti da veći broj worker procesa dovodi do ubrzanja uprkos povećanju kontekstnog prebacivanja. Najbolje je da u tom slučaju sprovedete testove pod opterećenjem i izmerite rezultate.
Sva podešavanja za NGINX radite u glavnoj konfiguracionoj datoteci koja se nalazi na putanji /etc/nginx/nginx.conf.
Takođe, za pojedinačne sajtove koriste se datoteke unutar direktorijuma /etc/nginx/sites-available/, dok aktivne konfiguracije povezujete kroz linkove u direktorijumu /etc/nginx/sites-enabled/.
Da biste izmenili konfiguraciju, koristite tekst editor poput Nano ili Vim sa administrativnim pravima, na primer komandama sudo nano /etc/nginx/nginx.conf ili sudo nano /etc/nginx/sites-available/ime_sajta.conf.
Ovde dajemo primer koda za prilagođavanje broja worker procesa:
worker_processes auto; # ili eksplicitna vrednost, npr. 4
events {
worker_connections 1024; # upariti kasnije sa realnim opterecenjem
multi_accept on;
}
U primeru iznad, worker_processes auto; govori NGINX-u da automatski detektuje broj CPU jezgara i pokrene odgovarajući broj radnih procesa. Ipak, nekad ćete želeti da eksplicitno navedete veću vrednost (recimo 2x broj jezgara) i da nakon toga testirate da li to daje bolje rezultate.
Upravljanje konekcijama (Worker Connections)
Parametar worker_connections definiše maksimalan broj paralelnih veza (konekcija) po radnom procesu. Podrazumevana vrednost je 512, ali ta vrednost može biti isuviše mala za opterećenja s velikim brojem istovremenih korisnika.
Kada NGINX opslužuje mnogo TLS saobraćaja, svaka posebna konekcija zahteva dodatno šifrovanje i dešifrovanje, što na kraju povećava opterećenje procesora.
Ako je uz to uključena gzip ili neka druga kompresija, to stvara još veče opterećenje za CPU, naročito pri velikom broju paralelnih veza. Ukoliko želite da saznate više o algoritmima i metodama za kompresiju podataka, preporučujemo da pročitate naš tekst Popularni algoritmi i metode za kompresiju podataka.
Da bi se obezbedilo da se svaka konekcija uredno zatvori tek nakon isporuke svih podataka, potrebno je da ostavite uključenu opciju lingering_close.
Primer koda za veću vrednost worker_connections:
worker_processes 4; # ili druga testirana vrednost
events {
worker_connections 2048;
# Omogucava da worker proces istovremeno prihvati veci broj konekcija
multi_accept on;
}
Kao i kod radnih procesa, preporuka je da eksperimentišete dok ne pronađete optimalno rešenje. Imajte u vidu da ne postoji neka univerzalna vrednost koja odgovara svima, jer zavisi od tipa aplikacije, prosečne veličine fajlova, TLS zahteva i brojnih drugih faktora.
Konfigurisanje NGINX-a kao balansera opterećenja (load-balancer)
NGINX često služi kao front-end sloj za raspodelu opterećenja između više back-end servera. Svrha ovoga je da ravnomernije rasporedi zahteve i obezbedi visoku dostupnost.
Kada se iza NGINX-a nalazi više serverskih instanci, on raspoređuje zahteve tako da ne zatrpa jednu instancu prevelikim opterećenjem. Ako neka od njih počne da prijavljuje greške, NGINX je odmah sklanja iz rotacije dok se ne oporavi, obezbeđujući na taj način stabilan i neprekidan rad sistema.
Ako web aplikacija koristi korisničke sesije, onda tzv. lepljive sesije (sticky sessions) drže sve zahteve jednog korisnika na istoj instanci, pa nema zabune sa prijavljivanjem ili personalizovanim podešavanjima.
Primer koda za osnovno balansiranje opterećenja
http {
upstream my_backend {
server 192.168.1.10:80 weight=2;
server 192.168.1.11:80;
server 192.168.1.12:80 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name moj-sajt.com;
location / {
proxy_pass http://my_backend;
}
}
}
U ovom primeru, weight=2 znači da će 192.168.1.10 dobijati veći udeo saobraćaja, a max_fails=3 i fail_timeout=30s određuju kada i na koliko dugo će back-end biti označen kao nedostupan.
Keširanje i kompresija statičkog sadržaja
Jedan od najefikasnijih načina ubrzanja web aplikacija jeste keširanje. Zahvaljujući keširanju, smanjuje se broj odlazaka ka back-end serveru ili disku. Ovo je posebno slučaj kada je reč o statičkim fajlovima (slike, CSS, JavaScript).
Server-side keš omogućava privremeno čuvanje sadržaja na NGINX-u, proxy Cache čuva odgovore od bekend servera, dok FastCGI Cache ubrzava isporuku dinamičkog sadržaja koji se ne menja često. To su najčešće rezultati API poziva ili stranice sa statistikama.
Client-side keš koristi HTTP zaglavlja Cache-Control i Expires kako bi klijent znao koliko dugo da drži resurse lokalno, pa se tako smanjuje broj ponovnih zahteva.
Kada je reč o kompresiji, gzip skraćuje veličinu odgovora i ubrzava prenos, što je naročito korisno u uslovima spore ili zagušene mreže.
Primer koda za keširanje i kompresiju
http {
# Definicija keš direktorijuma
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
server {
listen 80;
server_name moj-sajt.com;
# Primer setovanja Cache-Control zaglavlja
location ~* \.(css|js|jpg|jpeg|png|gif|ico)$ {
expires 7d;
add_header Cache-Control "public";
}
# Primer prostog proxy keša
location /api/ {
proxy_pass http://my_backend;
proxy_cache my_cache;
proxy_cache_valid 200 1m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
}
# Uključivanje gzip kompresije
gzip on;
gzip_types text/plain text/css application/json application/javascript application/xml;
gzip_comp_level 5;
}
}
U ovom primeru, definisali smo putanju za keš, aktivirali proxy keširanje za /api/ rutu i podesili zaglavlja za statičke fajlove (slike, CSS, JS). Takođe smo uključili gzip on; da bismo komprimovali određene MIME tipove.
Praćenje logova i baferovanje
Logovi spadaju među važne alate za dijagnostikovanje problema, praćenje performansi i razumevanje ponašanja korisnika. Tu razlikujemo dva osnovna loga.
Access log, koji beleži sve pristupe serveru, uključujući HTTP metode, status kodove, veličinu odgovora, IP adresu klijenta i korisnički agent i sa druge strane, error log, koji čuva informacije o greškama, poput nepravilno postavljene konfiguracije ili pojave 4xx i 5xx status kodova, a dodatno ukazuje i na sistemske probleme koji mogu ometati rad servera.
Da biste smanjili opterećenje diska, možete koristiti baferovanje logova. Pored toga, možete postaviti različite nivoe logovanja (info, warn, error, crit) za različite lokacije, kako biste ispratili problematične rute u većoj rezoluciji (debug) bez prevelikog opterećenja na celokupan sajt.
Primer koda za jednostavno baferovanje i odvojeno logovanje
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main buffer=16k flush=2s;
error_log /var/log/nginx/error.log warn;
server {
listen 80;
server_name moj-sajt.com;
location / {
# Standardni log nivo
access_log /var/log/nginx/access_main.log main;
proxy_pass http://my_backend;
}
location /debug/ {
# Dodatna detaljna evidencija za debugging
access_log /var/log/nginx/access_debug.log main;
# Ovde bi mogao da se ukljuci i rewrite_log on; u slucaju slozene konfiguracije
proxy_pass http://debug_backend;
}
}
}
U ovom primeru koristimo buffer=16k flush=2s kako bismo smanjili broj upisa na disk. Takođe, koristimo različite fajlove za standardni saobraćaj (/) i za rutu (/debug/) gde bismo možda želeli da imamo podrobnije praćenje.
Saveti za testiranje
Pre nego što primenite promenjene NGINX konfiguracije na produkcionom sistemu, dobro je imati testno okruženje identično produkciji. Tako možete proveriti uticaj novih podešavanja radnih procesa, keširanja ili parametara TLS-a na performanse, bez rizika da korisnici osete eventualne zastoje ili greške.
Ukoliko je moguće, probajte da koristite različite verzije NGINX-a i uporedite rezultate, kao i da testirate na serverima različitih konfiguracija (broj CPU jezgara, memorija, SSD vs. HDD i sl.). Sve to doprinosi uvidu u to gde leži potencijalni problem i kako se sistem ponaša pri povećanom saobraćaju ili kada se menjaju drugi uslovi.
Uvek pratite ključne indikatore performansi (KPI) kao što su prosečno vreme odziva, latencija, broj obrađenih zahteva u sekundi (RPS), iskorišćenost CPU-a i memorije, kao i tipične HTTP kodove. Ako primetite pogoršanje kod bilo kog parametra nakon promena, vreme je za dublje analize i nove korekcije.
Zaključak
Kao što ste videli, bez obzira na to da li NGINX koristite kao primarni web server, reverzni proksi, balancer opterećenja ili sistem keširanja, pravilno podešavanje može da napravi ogromnu razliku u brzini i pouzdanosti vašeg sajta ili aplikacije.
Imajte i u vidu to da je optimizacija NGINX-a proces kojim je potrebno da se bavite u kontinuitetu. Kako se vremenom vaša web aplikacija bude usložnjavala, tako ćete morati da dodatno prilagođavate podešavanja i testirate različite scenarije. Ukoliko budete pratili naše savete i najbolje prakse, vaš NGINX web server će uvek biti dobro parametrizovan i spreman i za one najzahtevnije zadatke.
