Blog članak

Objašnjene Apache MPM directive

Razumijte Apache MPM directive koje određuju konkurentnost, potrošnju memorije i obradu zahtjeva kroz Prefork, Worker i Event modele.

Kako se directive ponašaju i koje su uopće dostupne primarno ovisi o učitanom MPM-u. MPM je kratica za MultiProcess Modules i oni određuju osnovni način na koji Apache rješava multiprocessing. Obradit ćemo tri cjeline:

  1. General optimization
  2. Event/Worker optimization
  3. Prefork optimization

Svaki dio fokusira se na to kako directive utječu na performanse unutar pripadajućeg MPM-a i koje tipične stvari treba uzeti u obzir pri optimizaciji Apachea u tom kontekstu.

1. General optimization

IfModule

Važna directive koju treba razumjeti pri radu s Apache serverima je IfModule uvjetni blok. Sastoji se od dva dijela: početnog bloka koji prihvaća naziv modula ili izvornu datoteku modula i završnog bloka. Kada je zadani modul učitan u Apache, sve directive između početka i kraja IfModule bloka također se učitavaju u aktivnu konfiguraciju. Pogledajte primjer:

<ifModule mpm_prefork_module>
    MaxSpareServers 16
</ifModule>
Timeout 60

U ovom primjeru MaxSpareServers se definira samo kada je učitan mpm_prefork_module. Timeout se primjenjuje uvijek jer se nalazi izvan IfModule bloka.

IfModule blokovi služe održavanju kompatibilnosti Apache konfiguracije prilikom promjene modula. Directive su grupirane tako da se koriste samo kada je potreban modul doista učitan. Tako dobivate sintaktički ispravnu konfiguraciju čak i kada mijenjate module.

Ispravno omatanje direciva unutar IfModule blokova smatra se best practice pristupom u Apache konfiguraciji i treba ga slijediti radi bolje kompatibilnosti.

Timeout

Ovo je broj sekundi koliko Apache čeka za uobičajene I/O događaje. Apache će odustati od zahtjeva koji se ne dovrše prije zadane Timeout vrijednosti.

Prava vrijednost ovisi i o prometnim navikama i o aplikacijama koje hostate. Idealno, Timeout treba biti što niži, ali i dalje dovoljno visok da velika većina regularnog prometa radi bez problema. Veliki timeouti, posebno iznad jedne minute, otvaraju prostor za SlowLoris stil DoS napada i produžuju čekanje korisnika u browseru kada nešto pođe po zlu. Niži timeout omogućuje Apacheu brži oporavak od zapetljanih konekcija. Treba pronaći ravnotežu.

Nemojte povećavati globalni Timeout radi jednog skripta ili korisnika kojem treba dulje vrijeme. Takvi problemi obično se rješavaju kroz .htaccess ili include datoteku za točno taj skript.

KeepAlive

Jednostavan on|off prekidač uključuje KeepAlive protokol za podržane browsere. KeepAlive može donijeti i do 50% manje latencije te značajno poboljšati performanse Apachea. Funkcionira tako da browser ponovno koristi istu inicijalnu konekciju za naknadne zahtjeve koji se dogode unutar kratkog razdoblja.

KeepAlive je snažna funkcionalnost i u većini slučajeva treba biti uključen. Posebno dobro radi na modernim stranicama s mnogo elemenata jer smanjuje CPU i mrežni overhead.

S njim dolaze i dvije povezane directive: MaxKeepAliveRequests i KeepAliveTimeout, koje imaju važnu ulogu u finom podešavanju.

MaxKeepAliveRequests

Ova directive postavlja ograničenje na broj zahtjeva koje pojedinačna KeepAlive konekcija smije obraditi. Kada se limit dosegne, Apache prisilno zatvara konekciju i stvara novu za eventualne dodatne zahtjeve.

Idealna vrijednost ovisi o interpretaciji, ali općenito želite da bude barem jednaka najvećem broju elemenata na najposjećenijim stranicama servera.

Pravilo je da MaxKeepAliveRequests postavite na dvostruku vrijednost od najvećeg broja elemenata na tipičnim stranicama.

KeepAliveTimeout

Ova directive mjeri se u sekundama i definira koliko dugo konekcija ostaje neaktivna čekajući dodatne zahtjeve istog inicijatora. Budući da su takve konekcije dostupne samo tom inicijatoru, KeepAliveTimeout treba biti vrlo nizak. Niska vrijednost sprječava da previše KeepAlive konekcija blokira nove posjetitelje zbog prioriteta konekcije.

Veliki MaxKeepAliveRequests u kombinaciji s vrlo niskim KeepAliveTimeout dopušta aktivnim posjetiteljima ponovno korištenje konekcije, a istovremeno brzo oslobađa threadove od neaktivnih korisnika.

Preporuka konfiguracije: MaxKeepAliveRequests 500+ i KeepAliveTimeout 2. Najbolje radi na MPM Eventu.

2. Event/Worker optimization

Ovaj dio opisuje directive koje su važne kada radite s Worker baziranim MPM-ovima, uključujući i MPM Event i MPM Worker. To su multi-threaded rješenja i neke directive se drukčije ponašaju ovisno o učitanom MPM-u.

Kod Worker-based MPM-ova ServerLimit, ThreadsPerChild i MaxRequestWorkers snažno su povezani. Važno je razumjeti ulogu svake i kako promjena jedne utječe na ostale.

MPM Worker i MPM Event

MPM Event i MPM Worker u većini slučajeva rade gotovo identično. Razlika je vidljiva u načinu na koji rješavaju KeepAlive zahtjeve. MPM Worker zaključava threadove tijekom KeepAlive procesa, što direktno smanjuje broj threadova dostupnih za nove zahtjeve. MPM Event koristi poseban listener thread za svako dijete procesa. Taj listener obrađuje i regularne i KeepAlive zahtjeve pa zaključavanje threadova ne smanjuje kapacitet servera. Upravo zato je MPM Event bolji izbor, ali tek od Apachea 2.4 nadalje. Prije toga je bio nestabilan.

ServerLimit

ServerLimit predstavlja gornju granicu broja child procesa koje Apache smije imati. Praktična svrha mu je stvaranje hard limita kojim se server štiti od grešaka pri unosu MaxRequestWorkers vrijednosti. Time se sprječava stvaranje golemog broja procesa koje sustav ne može podnijeti, što može dovesti do downtimea, gubitka prihoda, reputacije ili čak podataka.

ServerLimit je izravno povezan s thrashing pointom. To je maksimalan broj child procesa koji Apache može pokrenuti prije nego što potrošnja memorije sklizne u stalni swap. ServerLimit treba uskladiti s tim izračunom.

ThreadsPerChild

Ova directive definira koliko threadova svaki Apache child može upravljati. Svaki aktivni thread može obraditi jedan zahtjev. Zadana vrijednost 25 dobro radi u većini slučajeva i predstavlja solidan balans između child procesa i threadova.

Postoji i gornja granica koju kontrolira ThreadLimit, a ona je po defaultu 64. Ako želite više od 64 threada po childu, morate prilagoditi i ThreadLimit.

Povećanje ove vrijednosti omogućuje svakom childu obradu većeg broja zahtjeva uz manju potrošnju memorije i veći MaxRequestWorkers. Velika prednost većeg broja threadova unutar jednog childa jest dijeljeni pristup memorijskom cacheu. Threadovi jednog childa mogu dijeliti cache, dok threadovi između childova to ne mogu. Veći broj threadova po childu zato može donijeti bolju izvedbu. Glavni nedostatak dolazi prilikom child recyclinga, kada se kapacitet servera privremeno smanjuje za broj threadova konfiguriranih u tom childu.

Snižavanje ThreadsPerChild radi suprotno. Tada vam treba više child procesa za isti MaxRequestWorkers, što povećava potrošnju memorije, ali smanjuje utjecaj recyclinga child procesa. Manje threadova znači i manje potencijalno “zapetljanih” threadova tijekom recycle postupka.

Pri postavljanju ThreadsPerChild uvijek razmišljajte o stvarnom server okruženju i hardveru.

ThreadLimit

ThreadLimit postavlja maksimalnu vrijednost za ThreadsPerChild. To je tvrdi strop koji štiti od tipfelera i pogrešnih unosa. Na jačim serverima ponekad ga treba povećati kada je sustavu potrebno više od zadanih 64 threada po childu.

MaxRequestWorkers / MaxClients

Ova directive postavlja granicu aktivnih worker threadova kroz sve child procese i radi kao soft limit, dok ServerLimit preuzima ulogu hard limita. Kada ukupan broj threadova dosegne ili prijeđe MaxRequestWorkers, Apache više ne pokreće nove child procese.

Određivanje MaxRequestWorkers ključno je za optimizaciju servera. Optimalna vrijednost ovisi o više promjenjivih faktora, što znači da konfiguraciju treba povremeno preispitivati na temelju prometa i korištenja resursa. Apache status Scoreboard izvrstan je alat za analizu performansi.

Na Worker-based MPM sustavima često radi izolirani third-party PHP handler poput mod_fcgid, PHP-FPM ili mod_lsapi. Takvi moduli izvršavaju PHP izvan Apachea i oslobađaju Apache za obradu lakših zahtjeva poput HTML-a, CSS-a, slika i sličnog. Zato Apache u tim setupima može podnijeti znatno veći broj zahtjeva, pa i više od 400 MaxRequestWorkers.

MinSpareThreads

Ovo je najmanji broj threadova koji trebaju ostati otvoreni i čekati nove zahtjeve. MinSpareThreads je višekratnik od ThreadsPerChild i ne može biti veći od MaxSpareThreads.

Preporuka je postaviti ga na 50% vrijednosti MaxRequestWorkers.

Spare threadovi su idle worker threadovi koji samo čekaju nove zahtjeve. Ako ih je manje od MinSpareThreads, Apache parent stvara novi child s još jednim paketom ThreadsPerChild threadova.

MaxSpareThreads

Ova directive određuje ukupan broj idle threadova dopuštenih na serveru kroz sve child procese. Ako je idle threadova više od tog limita, parent će gasiti child procese kako bi smanjio potrošnju memorije tijekom slabijeg prometa.

Ograničenje broja idle threadova korisno je na manjim serverima s hardverskim ograničenjima, ali na modernijem hardveru često više nije toliko nužno.

Na snažnijim serverima s puno RAM-a i više CPU jezgri moguće je raditi tzv. open throttle konfiguraciju. Tada su svi dostupni threadovi stalno spremni. Memorijska potrošnja Apachea tada ostaje visoka, ali odziv je maksimalno brz jer se izbjegava overhead pokretanja novih procesa u naletima prometa. U takvom setupu MinSpareThreads i MaxSpareThreads uskladite s MaxRequestWorkers.

StartServers

Ova directive definira početni broj child procesa koje Apache parent stvara kada se servis pokrene ili restartira. Najčešće ostaje nepromijenjena jer Apache sam kontinuirano prati broj child procesa i threadova te prema MinSpareThreads odlučuje treba li kreirati nove child procese.

Ako je računate ručno, StartServers dobivate tako da MaxRequestWorkers podijelite s ThreadsPerChild i zaokružite prema dolje. Tako se svi child procesi stvore odmah pri startu, bez čekanja, što je korisno na modernim serverima koji se povremeno restartaju radi promjene direciva.

MaxConnectionsPerChild / MaxRequestsPerChild

Ova directive određuje koliko zahtjeva jedan Apache child može obraditi ukupno kroz sve threadove koje kontrolira. Nakon što dosegne limit, child se reciklira.

Služi kao zaštita od slučajnih memory leakova. Neki dijelovi koda koje threadovi izvršavaju mogu curiti memoriju i s vremenom je učiniti nedostupnom drugim procesima. Postavljanje limita za MaxConnectionsPerChild osigurava da Apache povremeno reciklira procese i smanji učinak takvih curenja.

Ako koristite vanjske code handlere poput mod_fcgid, PHP-FPM ili mod_lsapi, često je potrebno postaviti MaxConnectionsPerChild na 0, dakle neograničeno, kako Apache ne bi prerano gasio threadove i uzrokovao povremene greške.

Ako sumnjate na memory leak, nemojte odmah postaviti nisku vrijednost. Krenite s 10.000 i spuštajte postupno.

3. Prefork optimization

Ovaj dio pokriva directive relevantne za MPM Prefork. Riječ je o non-threaded multiprocessing modulu dizajniranom prvenstveno radi kompatibilnosti. Sastoji se od jednog Apache parent procesa koji upravlja svim child procesima. Za razliku od Worker-based MPM-ova, MPM Prefork optimizira se jednostavnije jer postoji 1:1 odnos Apache procesa i dolaznih zahtjeva. No loše skalira s prometom i što je promet veći, treba mu više hardvera.

MaxRequestWorkers / MaxClients

Ova directive kontrolira gornju granicu child procesa koje Apache parent smije držati u memoriji istovremeno. Budući da svaki child obrađuje jedan zahtjev, to je ujedno i maksimalan broj simultanih zahtjeva koje server može podnijeti.

Ako je postavljena prenisko, Apache ne koristi sav raspoloživ hardver, što znači sporije učitavanje stranica i bačeni novac. Ako je previsoka, Apache može preopteretiti sustav i završiti u thrashing scenariju, s mogućim rušenjem servera i gubitkom podataka.

MinSpareServers

Ova directive definira minimalan broj idle child procesa koje Apache parent treba držati spremnima. Idle child je već preforkan Apache proces koji čeka novi zahtjev. To je bitno za brz odziv servera. Ako broj idle childova padne ispod zadane vrijednosti, Apache stvara novi child brzinom od jednog u sekundi dok ne zadovolji uvjet.

Nikada ovu vrijednost nemojte postaviti na nulu. Dobro je pravilo postaviti je na 25% MaxRequestWorkers vrijednosti.

MaxSpareServers

MaxSpareServers kontrolira maksimalan broj idle Apache child procesa koji smiju istovremeno raditi. Ako ih ima više, Apache gasi višak.

Ako je MaxSpareServers manji od MinSpareServers, Apache će ga automatski povećati na MinSpareServers + 1.

Dobro pravilo je postaviti ga na dvostruku vrijednost MinSpareServers.

Na serverima s puno RAM-a i više CPU jezgri moguće je koristiti open throttle pristup, gdje su svi child procesi stalno spremni. To povećava memorijsku potrošnju, ali daje najbolje moguće vrijeme odziva. U tom slučaju MinSpareServers i MaxSpareServers postavite jednako kao MaxRequestWorkers.

StartServers

StartServers definira koliko će Apache child procesa biti kreirano pri pokretanju. Rijetko se mijenja jer Apache inače sam odlučuje koliko child procesa treba.

Na modernim serverima koji periodično restartaju Apache radi novih konfiguracija ili rotacije logova, svaka sekunda downtimea je važna. Tada ima smisla StartServers postaviti jednako MinSpareServers vrijednosti kako bi startup bio brži.

ServerLimit

ServerLimit je gornja granica za MaxRequestWorkers i uglavnom služi kao zaštitni strop protiv pogrešnog unosa.

Treba ga prilagoditi ako server mora podnijeti više od zadanih 256 simultanih zahtjeva.

I ovdje se veže uz thrashing point. ServerLimit treba uskladiti s maksimalnim brojem child procesa koje hardver može podnijeti prije nego memorija sklizne u stalni swap.

Povećavanje ServerLimit nije preporučljivo s MPM Preforkom jer više od 256 simultanih zahtjeva u ovom modelu traži vrlo ozbiljan hardver.

MaxConnectionsPerChild / MaxRequestsPerChild

Ova directive predstavlja broj zahtjeva koje jedan Apache child može obraditi.

I ovdje služi kao zaštita od memory leakova. Kod koji Apache izvršava ponekad ima greške koje uzrokuju curenje memorije. S vremenom takva curenja smanjuju količinu iskoristive memorije child procesa. Recikliranje child procesa rješava taj problem.

Dobro pravilo je ne postavljati ovu vrijednost prenisko. Ako se pojave memory leak problemi, krenite s 10.000 i spuštajte postupno.

Povezane usluge

Ove su usluge usklađene s temom članka i daju čišći prijelaz od edukativnog sadržaja do konkretne implementacije.

Nastavite čitati

Prvo po zajedničkim kategorijama, a zatim po najjačem preklapanju u tagovima.