Web aplikacije se sada koriste svuda, a među svim transportnim protokolima, HTTP zauzima lavovski udio. Prilikom proučavanja nijansi razvoja web aplikacija, većina ljudi posvećuje vrlo malo pažnje operativnom sistemu na kojem te aplikacije zapravo rade. Razdvajanje razvoja (Dev) i operacija (Ops) samo je pogoršalo situaciju. Ali sa porastom DevOps kulture, programeri postaju odgovorni za pokretanje svojih aplikacija u oblaku, tako da je za njih veoma korisno da se temeljno upoznaju sa pozadinom operativnog sistema. Ovo je posebno korisno ako pokušavate da implementirate sistem za hiljade ili desetine hiljada istovremenih veza.
Ograničenja u web servisima su vrlo slična onima u drugim aplikacijama. Bilo da su u pitanju balanseri opterećenja ili serveri baze podataka, sve ove aplikacije imaju slične probleme u okruženju visokih performansi. Razumijevanje ovih osnovnih ograničenja i općenito kako ih prevladati pomoći će vam da ocijenite performanse i skalabilnost 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. Linux, bez ulaženja u osnove njihovog rada na nivou operativnog sistema. Iako postoji mnogo vrsta aplikacija, u ovoj seriji želim istražiti web aplikacije, a ne desktop aplikacije poput preglednika ili uređivača teksta. Ovaj materijal je namijenjen programerima i arhitektima koji žele razumjeti kako programi funkcionišu. Linux ili Unix i kako ih strukturirati za visoke performanse.
Linux Je server room operativni sistem, i najčešće vaše aplikacije rade na ovom OS-u. Iako kažem "Linux", većinu vremena možete sa sigurnošću pretpostaviti da se to odnosi na sve Unix-like operativne sisteme općenito. Međutim, nisam testirao priloženi kod na drugim sistemima. Dakle, ako ste zainteresirani za FreeBSD ili OpenBSD, rezultat se može razlikovati. Kada pokušam nešto Linux-specifično, onda to istaknem.
Iako ovo znanje možete koristiti da napravite aplikaciju od nule i ona će biti savršeno optimizirana, najbolje je to ne raditi. Ako napišete novi web server u C ili C++ za poslovnu aplikaciju vaše organizacije, ovo može biti vaš posljednji dan na poslu. Međutim, poznavanje strukture ovih aplikacija pomoći će pri odabiru postojećih programa. Moći ćete da uporedite sisteme zasnovane na procesima sa sistemima zasnovanim na nitima, kao i sa sistemima zasnovanim na događajima. Razumjet ćete i cijeniti zašto Nginx radi bolje od Apache httpd, zašto Python aplikacija zasnovana na Tornadu može poslužiti više korisnika u poređenju sa Python aplikacijom zasnovanom na Djangu.
ZeroHTTPd: Alat za učenje
je web server koji sam napisao od nule u C-u kao nastavno sredstvo. Nema vanjske zavisnosti, uključujući pristup Redis-u. Mi vodimo vlastite Redis procedure. Pogledajte ispod za više detalja.
Iako bismo mogli opširno raspravljati o teoriji, nema ništa bolje od pisanja koda, njegovog pokretanja i međusobnog poređenja svih serverskih arhitektura. Ovo je najočitija metoda. Stoga ćemo napisati jednostavan ZeroHTTPd web server koristeći svaki model: baziran na procesu, na nitima i na događaju. Hajde da pogledamo svaki od ovih servera i vidimo kako se oni međusobno ponašaju. ZeroHTTPd je implementiran u jednu datoteku C. Server baziran na događajima uključuje , odlična implementacija hash tablice koja dolazi u jednom zaglavlju. U drugim slučajevima nema zavisnosti, kako ne bi komplicirali projekat.
Kod je opširno komentiran kako biste ga lakše razumjeli. Budući da je jednostavan web server sa samo nekoliko linija koda, ZeroHTTPd je ujedno i minimalni okvir za web razvoj. Ima ograničenu funkcionalnost, ali može posluživati statičke datoteke i vrlo jednostavne "dinamičke" stranice. Moram reći da je ZeroHTTPd vrlo pogodan za učenje kako kreirati visokoperformansne stranice. Linux-aplikacije. Uglavnom, većina web servisa čeka zahtjeve, validira ih i obrađuje. To je upravo ono što će ZeroHTTPd uraditi. To je alat za učenje, a ne za produkciju. Nije sjajan u rukovanju greškama i vjerovatno se neće pohvaliti najboljim sigurnosnim praksama (oh da, koristio sam strcpy) ili pametnim trikovima jezika C. Ali nadam se da dobro radi svoj posao.

ZeroHTTPd početna stranica. Može prikazati različite tipove datoteka uključujući slike
Aplikacija za knjigu gostiju
Moderne web aplikacije obično nisu ograničene na statične datoteke. Imaju složene interakcije sa raznim bazama podataka, keš memorijama itd. Tako ćemo kreirati jednostavnu web aplikaciju pod nazivom "Knjiga gostiju" u kojoj posjetitelji ostavljaju unose pod svojim imenima. Knjiga gostiju pohranjuje ranije ostavljene unose. Tu je i brojač posjetitelja na dnu stranice.

Web aplikacija "Knjiga gostiju" ZeroHTTPd
Brojač posjetilaca i unosi u knjigu gostiju pohranjeni su u Redisu. Prilagođene rutine su implementirane za komunikaciju s Redisom; ne oslanjaju se na vanjsku biblioteku. Nisam veliki pobornik uvođenja vlastitog koda kada postoje javno dostupna i dobro testirana rješenja. Ali cilj ZeroHTTPd-a je proučavanje performansi. Linux i pristup vanjskim servisima, dok posluživanje HTTP zahtjeva ima značajan utjecaj na performanse. Potrebna nam je potpuna kontrola nad Redis komunikacijama u svakoj od naših serverskih arhitektura. U jednoj arhitekturi koristimo blokirajuće pozive, dok u drugima koristimo procedure zasnovane na događajima. Korištenje vanjske Redis klijentske biblioteke ne pruža ovu kontrolu. Nadalje, naš mali Redis klijent obavlja samo nekoliko funkcija (dobijanje, postavljanje i povećanje ključa; dobijanje i dodavanje u niz). Nadalje, Redis protokol je izuzetno elegantan i jednostavan. Ne zahtijeva čak ni nikakvu posebnu obuku. Sama činjenica da protokol obavlja sav svoj posao u stotinjak linija koda govori mnogo o tome koliko je dobro osmišljen.
Sljedeća slika pokazuje šta aplikacija radi kada klijent (pretraživač) zatraži /guestbookURL.

Kako funkcioniše aplikacija za knjigu gostiju
Kada je potrebno izdati stranicu knjige gostiju, postoji jedan poziv sistemu datoteka za čitanje šablona u memoriju i tri mrežna poziva Redis-u. Datoteka šablona sadrži većinu HTML sadržaja za stranicu na slici iznad. Postoje i posebni čuvari mjesta za dinamički dio sadržaja: postovi i brojač posjetitelja. Dobijamo ih od Redisa, ubacujemo ih na stranicu i pružamo klijentu potpuno formiran sadržaj. Treći poziv Redis-u se može izbjeći jer Redis vraća novu vrijednost ključa kada se poveća. Međutim, za naš server, koji ima asinkronu arhitekturu zasnovanu na događajima, mnogo mrežnih poziva je dobar test za potrebe učenja. Stoga odbacujemo Redis povratnu vrijednost broja posjetitelja i ispitujemo je posebnim pozivom.
Arhitektura servera ZeroHTTPd
Gradimo sedam verzija ZeroHTTPd-a sa istom funkcionalnošću ali različitim arhitekturama:
- Iterativno
- Fork server (jedan podređeni proces po zahtjevu)
- Pre-fork server (pre-forkiranje procesa)
- Server sa nitima izvršenja (jedna nit po zahtjevu)
- Server sa kreiranjem pre-thread-a
- Arhitektura zasnovana
poll() - Arhitektura zasnovana
epoll
Mjerimo performanse svake arhitekture tako što učitavamo server HTTP zahtjevima. Ali kada se porede visoko paralelne arhitekture, povećava se broj upita. Testiramo tri puta i izračunavamo prosjek.
Metodologija testiranja

ZeroHTTPd podešavanje testiranja opterećenja
Važno je da prilikom izvođenja testova sve komponente ne rade na istoj mašini. U ovom slučaju, OS ima dodatne troškove planiranja jer se komponente takmiče za CPU. Mjerenje nadopterećenja operativnog sistema svake od odabranih serverskih arhitektura jedan je od najvažnijih ciljeva ove vježbe. Dodavanje više varijabli će postati štetno za proces. Stoga postavka na gornjoj slici najbolje funkcionira.
Šta radi svaki od ovih servera?
- load.unixism.net: Ovo je mjesto gdje trčimo
ab, Apache Benchmark uslužni program. Generiše opterećenje potrebno za testiranje arhitekture naših servera. - nginx.unixism.net: Ponekad želimo da pokrenemo više od jedne instance serverskog programa. Da biste to učinili, Nginx server s odgovarajućim postavkama radi kao balansator opterećenja koji dolazi ab na naše serverske procese.
- zerohttpd.unixism.net: Ovdje pokrećemo naše serverske programe na sedam različitih arhitektura, jedan po jedan.
- redis.unixism.net: Ovaj server pokreće Redis demon, gdje se pohranjuju unosi u knjigu gostiju i brojači posjetitelja.
Svi serveri rade na istom procesorskom jezgru. Ideja je da se procijene maksimalne performanse svake arhitekture. Pošto su svi serverski programi testirani na istom hardveru, ovo je osnova za poređenje. Moje testno podešavanje se sastoji od virtuelnih servera iznajmljenih od Digital Oceana.
Šta merimo?
Možete mjeriti različite indikatore. Procenjujemo performanse svake arhitekture u datoj konfiguraciji tako što učitavamo servere zahtevima na različitim nivoima paralelizma: opterećenje raste sa 20 na 15 istovremenih korisnika.
Rezultati ispitivanja
Sljedeći grafikon prikazuje performanse servera na različitim arhitekturama na različitim nivoima paralelizma. Y-osa je broj zahtjeva u sekundi, x-osa su paralelne veze.



Ispod je tabela sa rezultatima.
zahtjeva u sekundi
paralelizam
iterativno
viljuška
pre-fork
streaming
pre-streaming
anketa
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 namaz
2138
5000
-
veliki namaz
1600
1100
2519
-
2235
8000
-
-
1200
veliki namaz
2451
-
2100
10
-
-
veliki namaz
-
2200
-
2200
11
-
-
-
-
2200
-
2122
12
-
-
-
-
970
-
1958
13
-
-
-
-
730
-
1897
14
-
-
-
-
590
-
1466
15
-
-
-
-
532
-
1281
Grafikon i tabela pokazuju da iznad 8000 istovremenih zahtjeva imamo samo dva preostala igrača: pre-fork i epoll. Kako se opterećenje povećava, server zasnovan na anketama postiže lošije rezultate od onog sa nitima. Pre-fork arhitektura je dostojan konkurent epollu: ovo je dokaz koliko dobro kernel funkcioniše. Linux planira veliki broj niti.
ZeroHTTPd izvorni kod
ZeroHTTPd izvorni kod . Za svaku arhitekturu postoji poseban direktorij.
ZeroHTTPd │ ├── 01_iterative │ ├── main.c ├── 02_forking │ ├── main.c ├── 03_preforking │ ├── main.c ├── main.c ├── 04. 05_prethreading │ ├── main.c ├── 06_poll │ ├── main.c ├── 07_epoll │ └── main.c ├── Makefile ├─ html ├── javno │ ├─── tu│ ├─── tu│ ├─── . png └── šabloni └── knjiga gostiju └── index.html
Pored sedam direktorija za sve arhitekture, postoje još dva u direktoriju najviše razine: public i templates. Prvi sadrži datoteku index.html i sliku sa prvog snimka ekrana. Tamo možete staviti druge fajlove i fascikle, a ZeroHTTPd bi te statičke fajlove trebao poslužiti bez ikakvih problema. Ako se putanja u pretraživaču poklapa sa putanjom u javnoj mapi, tada ZeroHTTPd traži datoteku index.html u ovom direktoriju. Sadržaj za knjigu gostiju se generira dinamički. Ima samo početnu stranicu, a njegov sadržaj je zasnovan na datoteci 'templates/guestbook/index.html'. ZeroHTTPd lako dodaje dinamičke stranice za proširenje. Ideja je da korisnici mogu dodati šablone u ovaj direktorij i proširiti ZeroHTTPd prema potrebi.
Za izgradnju svih sedam servera, pokrenite make all iz direktorija najviše razine - i sve verzije će se pojaviti u ovom direktoriju. Izvršne datoteke traže javne i predloške direktorije u direktoriju iz kojeg su pokrenute.
Linux API
Da biste razumjeli informacije u ovoj seriji članaka, ne morate biti dobro upućeni u Linux API. Međutim, preporučujem da pročitate više o ovoj temi; postoji mnogo referentnih resursa na internetu. Iako ćemo se dotaknuti nekoliko kategorija Linux API-ja, naš fokus će biti prvenstveno na procesima, nitima, događajima i mrežnom steku. Pored knjiga i članaka o Linux API, također preporučujem čitanje priručnika za sistemske pozive i korištene bibliotečke funkcije.
Performanse i skalabilnost
Jedna napomena o performansama i skalabilnosti. Teoretski, nema veze između njih. Možete imati web servis koji radi vrlo dobro, s vremenom odziva od nekoliko milisekundi, ali se uopće ne povećava. Isto tako, može postojati web aplikacija sa lošim performansama kojoj je potrebno nekoliko sekundi da odgovori, ali se povećava za desetine kako bi obradila desetine hiljada istovremenih korisnika. Međutim, kombinacija visokih performansi i skalabilnosti je vrlo moćna kombinacija. Aplikacije visokih performansi uglavnom štedljivo koriste resurse i na taj način efikasno opslužuju više istovremenih korisnika na serveru, smanjujući troškove.
CPU i I/O zadaci
Konačno, u računarstvu uvijek postoje dvije moguće vrste zadataka: za I/O i CPU. Prijem zahtjeva preko Interneta (mrežni I/O), posluživanje datoteka (mrežni i disk I/O), komunikacija sa bazom podataka (mrežni i disk I/O) su sve I/O aktivnosti. Neki upiti za bazu podataka mogu biti malo CPU-intenzivni (sortiranje, u prosjeku milion rezultata, itd.). Većina web aplikacija ograničena je maksimalnim mogućim I/O, a procesor se rijetko koristi punim kapacitetom. Kada vidite da neki I/O zadatak koristi puno CPU-a, to je najvjerovatnije znak loše arhitekture aplikacije. To može značiti da se CPU resursi troše na upravljanje procesima i promjenu konteksta - a to nije sasvim korisno. Ako radite nešto kao što je obrada slika, konverzija audio datoteka ili strojno učenje, aplikacija zahtijeva moćne CPU resurse. Ali za većinu aplikacija to nije slučaj.
Saznajte više o arhitekturi servera
izvor: www.habr.com
