Web aplikacije se danas koriste svugdje, a meÄu svim transportnim protokolima HTTP zauzima najveÄi dio. Kada se prouÄavaju nijanse razvoja web aplikacija, veÄina posveÄuje vrlo malo pažnje operativnom sustavu na kojem se te aplikacije zapravo pokreÄu. Razdvajanje razvoja (Dev) i operacija (Ops) samo je pogorÅ”avalo situaciju. No, s porastom DevOps kulture, programeri poÄinju preuzimati odgovornost za pokretanje svojih aplikacija u oblaku, stoga im je od velike koristi detaljno upoznavanje sa backendom operativnog sustava. To je posebno korisno ako pokuÅ”avate postaviti sustav za tisuÄe ili desetke tisuÄa istodobnih veza.
OgraniÄenja u web uslugama vrlo su sliÄna onima u drugim aplikacijama. Bilo da se radi o balansiranim optereÄenjima ili poslužiteljima baza podataka, sva ta rjeÅ”enja imaju sliÄne probleme u visoko performansnim okruženjima. Razumijevanje tih temeljnih ograniÄenja i naÄina na koje ih možemo prevladati opÄenito Äe omoguÄiti procjenu performansi i skalabilnosti vaÅ”ih web aplikacija.
PiÅ”em ovu seriju Älanaka kao odgovor na pitanja mladih programera koji žele postati dobro informirani sistemski arhitekti. NemoguÄe je jasno razumjeti metode optimizacije aplikacija na Linuxu bez uranjanja u osnove, kako one rade na razini operativnog sustava. Iako postoji mnogo vrsta aplikacija, u ovom ciklusu želim istražiti mrežne aplikacije, a ne desktop aplikacije poput preglednika ili tekstualnog urednika. Ovaj materijal namijenjen je programerima i arhitektama koji žele shvatiti kako funkcioniraju programi na Linuxu ili Unixu i kako ih strukturirati za visoke performanse.
Linux je poslužiteljski operativni sustav, i najÄeÅ”Äe vaÅ”e aplikacije rade upravo na ovom OS-u. Iako govorim "Linux", veÄinu vremena možete s povjerenjem pretpostaviti da se misli na sve Unix-sliÄne operativne sustave opÄenito. Ipak, nisam testirao prateÄi kod na drugim sustavima. Dakle, ako vas zanima FreeBSD ili OpenBSD, rezultati se mogu razlikovati. Kada isprobavam neÅ”to Å”to je specifiÄno za Linux, to jasno naglaÅ”avam.
Iako možete iskoristiti steÄeno znanje za izradu aplikacije od nule koja Äe biti odliÄno optimizirana, bolje je to ne raditi. Ako napiÅ”ete novi web poslužitelj u C ili C++ za poslovnu aplikaciju vaÅ”e organizacije, možda Äe to biti vaÅ” posljednji dan na poslu. Ipak, poznavanje strukture tih aplikacija pomoÄi Äe vam u odabiru veÄ postojeÄih programa. MoÄi Äete usporeÄivati sustave temeljem procesa, sustavima temeljenim na nitima, kao i temeljenim na dogaÄajima. Razumjet Äete i cijeniti zaÅ”to Nginx radi bolje od Apache httpd-a, zaÅ”to aplikacija Python temeljena na Tornadu može opslužiti viÅ”e korisnika u usporedbi s aplikacijom Python temeljene na Djangou.
ZeroHTTPd: alat za uÄenje
Ā ā web poslužitelj koji sam napisao od nule u C-u kao alat za uÄenje. Nemamo vanjskih ovisnosti, ukljuÄujuÄi pristup Redis-u. PokreÄemo vlastite Redis procedure. ViÅ”e informacija možete pronaÄi u nastavku.
Iako bismo mogli dugo raspravljati o teoriji, nema niÄega boljeg od pisanja koda, pokretanja i usporedbe svih arhitektura poslužitelja. Ovo je najjasnija metoda. Zato Äemo napisati jednostavni web poslužitelj ZeroHTTPd, koristeÄi svaki model: temeljen na procesima, nitima i dogaÄajima. Provjerit Äemo svaki od ovih poslužitelja i vidjeti kako rade u usporedbi jedni s drugima. ZeroHTTPd je implementiran u jednoj C datoteci. U sustav poslužitelja temeljenog na dogaÄajima ukljuÄena je , izvrsna implementacija hash tablice koja dolazi u jednom zaglavlju. U ostalim sluÄajevima nema ovisnosti kako bi se izbjeglo kompliciranje projekta.
Kod sadrži mnogo komentara kako bi pomogao razumijevanju. Kao jednostavan web poslužitelj u nekoliko redaka koda, ZeroHTTPd takoÄer predstavlja minimalni okvir za web razvoj. Ima ograniÄene funkcionalnosti, ali može isporuÄivati statiÄne datoteke i vrlo jednostavne "dinamiÄke" stranice. Moram reÄi da je ZeroHTTPd dobar alat za uÄenje kako stvarati visoko performatne Linux aplikacije. Uglavnom, veÄina web usluga Äeka na zahtjeve, provjerava ih i obraÄuje. To Äe raditi ZeroHTTPd. To je alat za uÄenje, a ne za produkciju. Nije jak u obradi pogreÅ”aka i vjerojatno se ne može pohvaliti najboljim praksama sigurnosti (oh da, koristio sam strcpy) ili neobiÄnim trikovima jezika C. Ali se nadam da Äe se dobro snaÄi u svom zadatku.

PoÄetna stranica ZeroHTTPd. Može izdavati razliÄite tipove datoteka, ukljuÄujuÄi slike.
Aplikacija za knjigu gostiju.
Moderne web aplikacije obiÄno nisu ograniÄene na statiÄke datoteke. Imaju složene interakcije s raznim bazama podataka, keÅ”ovima itd. Stoga Äemo stvoriti jednostavnu web aplikaciju pod nazivom "Knjiga gostiju", gdje posjetitelji ostavljaju zapise pod svojim imenima. U knjizi gostiju se Äuvaju prethodno ostavljeni zapisi. TakoÄer, na dnu stranice postoji brojÄanik posjetitelja.

Web aplikacija "Knjiga gostiju" ZeroHTTPd.
BrojÄanik posjetitelja i zapisi knjige gostiju Äuvaju se u Redis-u. Za komunikaciju s Redis-om implementirane su vlastite procedure, koje ne ovise o vanjskoj biblioteci. Nisam veliki obožavatelj koriÅ”tenja domaÄeg koda kada postoje javno dostupna i dobro testirana rjeÅ”enja. Ali cilj ZeroHTTPd-a je istražiti performanse Linux-a i pristup vanjskim uslugama, dok održavanje HTTP zahtjeva ozbiljno utjeÄe na performanse. Moramo potpuno kontrolirati komunikaciju s Redis-om u svakoj od naÅ”ih serverskih arhitektura. U jednoj arhitekturi koristimo blokirajuÄe pozive, a u drugima procedure temeljene na dogaÄajima. KoriÅ”tenje vanjske klijentske biblioteke Redis ne bi omoguÄilo takvu kontrolu. Osim toga, naÅ” mali Redis klijent izvodi samo nekoliko funkcija (dobivanje, postavljanje i poveÄanje kljuÄa; dobivanje i dodavanje u niz). TakoÄer, Redis protokol je iznimno elegantan i jednostavan. Njega Äak ne treba posebno uÄiti. Samo to Å”to cijeli posao protokol obavlja s otprilike stotinjak redaka koda govori koliko je dobro osmiÅ”ljen.
Na sljedeÄem dijagramu prikazano je ponaÅ”anje aplikacije kada klijent (preglednik) Å”alje zahtjev. /guestbookURL.

Mehanizam rada aplikacije knjige gostiju.
Kada treba prikazati stranicu gostujuÄe knjige, izvrÅ”ava se jedan poziv prema datoteÄnom sustavu za uÄitavanje predloÅ”ka u memoriju i tri mrežna poziva prema Redis-u. Datoteka predloÅ”ka sadrži veÄinu HTML sadržaja za stranicu na gornjem ekranu. Tu su i posebne oznake za dinamiÄki dio sadržaja: unose i brojaÄ posjetitelja. Dobivamo ih iz Redis-a, umetnemo na stranicu i isporuÄimo klijentu potpuno oblikovani sadržaj. TreÄi poziv Redis-u možemo izbjeÄi, jer Redis vraÄa novu vrijednost kljuÄa prilikom poveÄanja. MeÄutim, za naÅ” poslužitelj s asinkronom arhitekturom temeljenom na dogaÄajima, mnogo mrežnih poziva je dobar test u obrazovne svrhe. Tako odbacujemo vraÄenu vrijednost Redis-a o broju posjetitelja i tražimo je zasebnim pozivom.
Poslužiteljske arhitekture ZeroHTTPd
Gradimo sedam verzija ZeroHTTPd s istom funkcionalnoÅ”Äu, ali razliÄitim arhitekturama:
- Iterativna
- Fork poslužitelj (jedan podproces po zahtjevu)
- Pre-fork poslužitelj (prethodno forkiranje procesa)
- Poslužitelj s izvoÄenjem niti (jedna nit po zahtjevu)
- Poslužitelj s prethodnim stvaranjem niti
- Arhitektura temeljena na
poll() - Arhitektura temeljena na
epoll
Mjerimo performanse svake arhitekture optereÄujuÄi poslužitelj HTTP zahtjevima. MeÄutim, prilikom usporedbe arhitektura s visokim stupnjem paralelizma, broj zahtjeva se poveÄava. Testiramo tri puta i raÄunamo prosjek.
Metodologija testiranja

Postavka za optereÄujuÄe testiranje ZeroHTTPd
Važno je da prilikom izvoÄenja testova svi sastavni dijelovi ne rade na jednoj maÅ”ini. U tom sluÄaju, operativni sustav nosi dodatne troÅ”kove planiranja jer se dijelovi natjeÄu za CPU. Mjerenje troÅ”kova operativnog sustava s svakom od odabranih poslužiteljskih arhitektura jedan je od najvažnijih ciljeva ove vježbe. Dodavanje veÄeg broja varijabli bit Äe pogubno za proces. Stoga konfiguracija na gornjoj slici najbolje funkcionira.
Å to Äini svaki od ovih poslužitelja
- load.unixism.net: ovdje pokreÄemo
ab, Apache Benchmark alat. Generira optereÄenje potrebno za testiranje naÅ”ih poslužiteljskih arhitektura. - nginx.unixism.net: ponekad želimo pokrenuti viÅ”e od jednog primjerka poslužiteljske aplikacije. Za to Nginx poslužitelj s odgovarajuÄim postavkama radi kao balansirnik optereÄenja koji dolazi od ab naÅ”e poslužiteljske procese.
- zerohttpd.unixism.net: ovdje pokreÄemo naÅ”e poslužiteljske programe na sedam razliÄitih arhitektura, jedan po jedan.
- redis.unixism.net: na ovom poslužitelju radi daemon Redis, gdje se pohranjuju zapisi u knjigu gostiju i broj posjetitelja.
Svi poslužitelji rade na jednom procesorskom jezgru. Ideja je procijeniti maksimalnu izvedbu svake od arhitektura. BuduÄi da se svi poslužiteljski programi testiraju na jednoj opremi, to je osnovna razina za njihovo usporeÄivanje. Moja testna postavka sastoji se od virtualnih poslužitelja, iznajmljenih od Digital Oceana.
Å to mjerimo?
Mogu se izmjeriti razliÄiti pokazatelji. Procjenjujemo izvedbu svake arhitekture u ovoj konfiguraciji, optereÄujuÄi poslužitelje upitima na razliÄitim razinama paralelizma: optereÄenje raste od 20 do 15,000 istodobnih korisnika.
Rezultati testova
Na sljedeÄem dijAGRAMU prikazana je izvedba poslužitelja na razliÄitim arhitekturama pri razliÄitim razinama paralelizma. Na y-osi ā broj upita po sekundi, na x-osi ā paralelne veze.



Ispod je tablica s rezultatima.
upita po sekundi
paralelizam
iterativno
fork
pre-fork
treding
pre-threading
poll
epoll
20
7
112
2100
1800
2250
1900
2050
50
7
190
2200
1700
2200
2000
2000
100
7
245
2200
1700
2200
2150
2100
200
7
330
2300
1750
2300
2200
2100
300
ā
380
2200
1800
2400
2250
2150
400
ā
410
2200
1750
2600
2000
2000
500
ā
440
2300
1850
2700
1900
2212
600
ā
460
2400
1800
2500
1700
2519
700
ā
460
2400
1600
2490
1550
2607
800
ā
460
2400
1600
2540
1400
2553
900
ā
460
2300
1600
2472
1200
2567
1000
ā
475
2300
1700
2485
1150
2439
1500
ā
490
2400
1550
2620
900
2479
2000
ā
350
2400
1400
2396
550
2200
2500
ā
280
2100
1300
2453
490
2262
3000
ā
280
1900
1250
2502
veliki raspon
2138
5000
ā
veliki raspon
1600
1100
2519
ā
2235
8000
ā
ā
1200
veliki raspon
2451
ā
2100
10Ā 000
ā
ā
veliki raspon
ā
2200
ā
2200
11Ā 000
ā
ā
ā
ā
2200
ā
2122
12Ā 000
ā
ā
ā
ā
970
ā
1958
13Ā 000
ā
ā
ā
ā
730
ā
1897
14Ā 000
ā
ā
ā
ā
590
ā
1466
15Ā 000
ā
ā
ā
ā
532
ā
1281
Iz grafikona i tablice vidljivo je da iznad 8000 istodobnih upita ostaju samo dva igraÄa: pre-fork i epoll. Kako optereÄenje raste, poslužitelj temeljen na poll radi loÅ”ije od threaded. Arhitektura s prethodnim stvaranjem niti predstavlja dostojnu konkurenciju epoll-u: to je svjedoÄanstvo koliko dobro kernal Linuxa upravlja velikim brojem niti.
Izvorni kod ZeroHTTPd
Izvorni kod ZeroHTTPd . Za svaku arhitekturu zaseban direktorij.
ZeroHTTPd
ā
āāā 01_iterative
ā āāā main.c
āāā 02_forking
ā āāā main.c
āāā 03_preforking
ā āāā main.c
āāā 04_threading
ā āāā main.c
āāā 05_prethreading
ā āāā main.c
āāā 06_poll
ā āāā main.c
āāā 07_epoll
ā āāā main.c
āāā Makefile
āāā public
ā āāā index.html
ā āāā tux.png
āāā templates
āāā guestbook
āāā index.htmlOsim sedam direktorija za sve arhitekture, u glavnom direktoriju postoje joÅ” dva: public i templates. U prvom se nalazi datoteka index.html i slika s prvog snimka ekrana. Tamo možete staviti druge datoteke i mape, a ZeroHTTPd bi trebao bez problema poslužiti te statiÄne datoteke. Ako putanja u pregledniku odgovara putanji u mapi public, ZeroHTTPd pretražuje ovaj direktorij za datoteku index.html. Sadržaj za gostujuÄu knjigu generira se dinamiÄki. Ima samo poÄetnu stranicu, a njezin sadržaj temelji se na datoteci ātemplates/guestbook/index.htmlā. U ZeroHTTPd lako se dodaju dinamiÄke stranice za proÅ”irenje. Ideja je da korisnici mogu dodavati template u ovaj direktorij i proÅ”irivati ZeroHTTPd prema potrebi.
Za izgradnju svih sedam poslužitelja pokrenite make all iz glavnog direktorija ā i sve gradnje Äe se pojaviti u ovom direktoriju. IzvrÅ”ne datoteke traže mape public i templates u onom direktoriju iz kojeg su pokrenute.
Linux API
Da biste razumjeli informacije u ovom ciklusu Älanaka, nije potrebno dobro poznavati Linux API. MeÄutim, preporuÄujem da proÄitate viÅ”e o ovoj temi, na mreži ima mnogo referentnih izvora. Iako Äemo se dotaknuti nekoliko kategorija Linux API-ja, naÅ”a Äe se pažnja uglavnom usredotoÄiti na procese, niti, dogaÄaje i mrežni stog. Osim knjiga i Älanaka o Linux API-ju, takoÄer preporuÄujem da proÄitate mann priruÄnike za sistemske pozive i koriÅ”tene biblioteÄke funkcije.
Performanse i skalabilnost
Jedna napomena o performansama i skalabilnosti. Teoretski, izmeÄu njih nema nikakve povezanosti. Možete imati web uslugu koja radi vrlo dobro, s vremenom odgovora od nekoliko milisekundi, ali se uopÄe ne može skalirati. BaÅ” kao Å”to može postojati loÅ”e izvedena web aplikacija koja traži nekoliko sekundi za odgovor, ali se može skalirati za desetine da bi obradila desetke tisuÄa istovremenih korisnika. Ipak, kombinacija visoke izvedbe i skalabilnosti je vrlo snažna kombinacija. Visoko performansni programi u cjelini ekonomiÄno koriste resurse i tako efikasno opslužuju viÅ”e istovremenih korisnika na poslužitelju, smanjujuÄi troÅ”kove.
Zadaci CPU i I/O
Na kraju, u raÄunanju uvijek postoje dva moguÄa tipa zadataka: za I/O i CPU. Primanje zahtjeva putem interneta (mrežni ulaz-izlaz), upravljanje datotekama (mrežni i diskovni ulaz-izlaz), komunikacija s bazom podataka (mrežni i diskovni ulaz-izlaz) ā sve su to I/O radnje. Neki zahtjevi za BDP-om mogu malo opteretiti CPU (sortiranje, izraÄunavanje prosjeka milijun rezultata itd.). VeÄina web aplikacija ograniÄena je na maksimalnu moguÄu I/O, dok se procesor rijetko koristi punom snagom. Kada primijetite da se za odreÄeni zadatak ulaz-izlaz koristi mnogo CPU-a, vjerojatno je to znak loÅ”e arhitekture aplikacije. To može znaÄiti da se resursi CPU-a troÅ”e na upravljanje procesima i prebacivanje konteksta ā i to nije posve korisno. Ako radite neÅ”to poput obrade slika, konverzije audio datoteka ili strojnog uÄenja, tada aplikacija zahtijeva jake CPU resurse. No za veÄinu aplikacija to nije sluÄaj.
Detaljnije o servernim arhitekturama
Izvor: habr.com
