Izvedba Linux mrežne aplikacije. Uvod

Web aplikacije se sada koriste posvuda, a među svim transportnim protokolima HTTP zauzima lavovski udio. Kada proučavaju nijanse razvoja web aplikacija, većina ljudi obraća vrlo malo pažnje na operativni sustav na kojem se te aplikacije zapravo izvode. Razdvajanje razvoja (Dev) i operacija (Ops) samo je pogoršalo situaciju. Ali s porastom DevOps kulture, programeri postaju odgovorni za pokretanje svojih aplikacija u oblaku, pa je vrlo korisno za njih da se temeljito upoznaju s pozadinom operativnog sustava. Ovo je posebno korisno ako pokušavate postaviti sustav za tisuće ili desetke tisuća istovremenih veza.

Ograničenja u web uslugama vrlo su slična onima u drugim aplikacijama. Bilo da se radi o balanserima opterećenja ili poslužiteljima baza podataka, sve ove aplikacije imaju slične probleme u okruženju visokih performansi. Razumijevanje ovih temeljnih ograničenja i kako ih općenito prevladati pomoći će vam u procjeni izvedbe i skalabilnosti vaših web aplikacija.

Ovu seriju članaka pišem kao odgovor na pitanja mladih programera koji žele postati dobro informirani arhitekti sustava. Nemoguće je jasno razumjeti tehnike optimizacije Linux aplikacija bez poniranja u osnove njihovog rada na razini operativnog sustava. Iako postoji mnogo vrsta aplikacija, u ovoj seriji želim istražiti aplikacije temeljene na webu, a ne aplikacije za stolna računala kao što su preglednik ili uređivač teksta. Ovaj je materijal namijenjen programerima i arhitektima koji žele razumjeti kako rade Linux ili Unix programi i kako ih strukturirati za visoke performanse.

Linux je poslužiteljska soba operativni sustav, a najčešće se vaše aplikacije pokreću na ovom OS-u. Iako kažem "Linux", većinu vremena sa sigurnošću možete pretpostaviti da mislim na sve operativne sustave slične Unixu općenito. Međutim, nisam testirao prateći kod na drugim sustavima. Dakle, ako ste zainteresirani za FreeBSD ili OpenBSD, vaši rezultati mogu varirati. Kad isprobam nešto specifično za Linux, istaknem to.

Iako ovo znanje možete koristiti za izradu aplikacije od nule i ona će biti savršeno optimizirana, najbolje je to ne činiti. Ako pišete novi web poslužitelj 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 usporediti sustave koji se temelje na procesu sa sustavima koji se temelje na nitima, kao i onima koji se temelje na događajima. Razumjet ćete i cijeniti zašto Nginx radi bolje od Apache httpd, zašto Python aplikacija temeljena na Tornadu može poslužiti više korisnika u usporedbi s Python aplikacijom temeljenom na Djangu.

ZeroHTTPd: Alat za učenje

ZeroHTTPd je web poslužitelj koji sam napisao od nule u C-u kao alat za podučavanje. Nema vanjskih ovisnosti, uključujući pristup Redisu. Vodimo vlastite Redis procedure. Više detalja potražite u nastavku.

Iako bismo mogli dugo raspravljati o teoriji, nema ništa bolje od pisanja koda, njegovog pokretanja i međusobnog uspoređivanja svih serverskih arhitektura. Ovo je najočitija metoda. Stoga ćemo napisati jednostavan ZeroHTTPd web poslužitelj koristeći svaki model: temeljen na procesu, temeljen na nitima i temeljen na događajima. Provjerimo svaki od ovih poslužitelja i vidimo kako rade u usporedbi jedan s drugim. ZeroHTTPd je implementiran u jednoj datoteci C. Poslužitelj temeljen na događajima uključuje uthash, izvrsna implementacija hash tablice koja dolazi u jednoj datoteci zaglavlja. U ostalim slučajevima nema ovisnosti, kako ne bi komplicirali projekt.

Postoji mnogo komentara u kodu koji će vam pomoći da razumijete. Budući da je jednostavan web poslužitelj u nekoliko redaka koda, ZeroHTTPd je također minimalni okvir za web razvoj. Ima ograničenu funkcionalnost, ali može posluživati ​​statične datoteke i vrlo jednostavne "dinamičke" stranice. Moram reći da je ZeroHTTPd dobar za učenje kako stvoriti Linux aplikacije visokih performansi. Uglavnom, većina web servisa čeka zahtjeve, provjerava ih i obrađuje. To je upravo ono što će ZeroHTTPd učiniti. Ovo je alat za učenje, a ne za proizvodnju. Nije dobar u rješavanju pogrešaka i malo je vjerojatno da će se pohvaliti najboljom sigurnosnom praksom (o da, koristio sam strcpy) ili pametnim trikovima jezika C. Ali nadam se da dobro obavlja svoj posao.

Izvedba Linux mrežne aplikacije. Uvod
ZeroHTTPd početna stranica. Može ispisati različite vrste 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 s raznim bazama podataka, predmemorijama itd. Stoga ćemo izraditi jednostavnu web aplikaciju pod nazivom "Knjiga gostiju" gdje posjetitelji ostavljaju unose pod svojim imenom. Knjiga gostiju pohranjuje ranije ostavljene zapise. Na dnu stranice nalazi se i brojač posjetitelja.

Izvedba Linux mrežne aplikacije. Uvod
Web aplikacija "Knjiga gostiju" ZeroHTTPd

Brojač posjetitelja i unosi u knjigu gostiju pohranjuju se u Redis. Za komunikaciju s Redisom implementirane su vlastite procedure koje ne ovise o vanjskoj knjižnici. Nisam veliki ljubitelj uvođenja homebrew koda kada postoje javno dostupna i dobro testirana rješenja. Ali svrha ZeroHTTPd-a je proučavanje performansi Linuxa i pristupa vanjskim uslugama, dok posluživanje HTTP zahtjeva ima ozbiljan utjecaj na performanse. Moramo u potpunosti kontrolirati komunikaciju s Redisom u svakoj od naših poslužiteljskih arhitektura. U nekim arhitekturama koristimo blokiranje poziva, u drugima koristimo procedure temeljene na događajima. Korištenje vanjske klijentske knjižnice Redis neće omogućiti ovu kontrolu. Dodatno, naš mali Redis klijent izvodi samo nekoliko funkcija (dobivanje, postavljanje i povećanje ključa; dobivanje i dodavanje nizu). Osim toga, Redis protokol je iznimno elegantan i jednostavan. Ne morate ga ni posebno učiti. Sama činjenica da protokol obavlja sav posao u stotinjak redaka koda pokazuje koliko je dobro promišljen.

Sljedeća slika pokazuje što aplikacija radi kada klijent (preglednik) zatraži /guestbookURL.

Izvedba Linux mrežne aplikacije. Uvod
Kako radi aplikacija knjiga gostiju

Kada je potrebno izdati stranicu knjige gostiju, postoji jedan poziv sustavu datoteka za čitanje predloška u memoriju i tri mrežna poziva Redisu. Datoteka predloška sadrži većinu HTML sadržaja za stranicu na gornjoj snimci zaslona. Postoje i posebna rezervirana mjesta za dinamički dio sadržaja: objave i brojač posjetitelja. Dobivamo ih od Redisa, ubacujemo u stranicu i klijentu dajemo potpuno oblikovan sadržaj. Treći poziv Redisu može se izbjeći jer Redis vraća novu vrijednost ključa kada se poveća. Međutim, za naš poslužitelj, koji ima asinkronu arhitekturu temeljenu na događajima, mnogo mrežnih poziva dobar je test za potrebe učenja. Stoga odbacujemo Redisovu povratnu vrijednost broja posjetitelja i postavljamo upit posebnim pozivom.

Arhitekture poslužitelja ZeroHTTPd

Gradimo sedam verzija ZeroHTTPd-a s istom funkcionalnošću, ali različitim arhitekturama:

  • Iterativno
  • Fork poslužitelj (jedan podređeni proces po zahtjevu)
  • Pre-fork poslužitelj (pre-fork procesa)
  • Poslužitelj s izvršnim nitima (jedna nit po zahtjevu)
  • Poslužitelj s prethodnim stvaranjem niti
  • Temeljeno na arhitekturi poll()
  • Temeljeno na arhitekturi epoll

Mjerimo performanse svake arhitekture učitavanjem poslužitelja HTTP zahtjevima. Ali kada se uspoređuju visoko paralelne arhitekture, broj upita se povećava. Testiramo tri puta i izračunavamo prosjek.

Metodologija ispitivanja

Izvedba Linux mrežne aplikacije. Uvod
Postavka testiranja opterećenja ZeroHTTPd

Važno je da prilikom izvođenja testova sve komponente ne rade na istom stroju. U ovom slučaju, OS stvara dodatne troškove planiranja jer se komponente natječu za CPU. Mjerenje opterećenja operativnog sustava za svaku od odabranih poslužiteljskih arhitektura jedan je od najvažnijih ciljeva ove vježbe. Dodavanje više varijabli postat će štetno za proces. Stoga postavka na gornjoj slici najbolje funkcionira.

Što svaki od ovih poslužitelja radi?

  • load.unixism.net: Ovdje trčimo ab, Apache Benchmark uslužni program. Generira opterećenje potrebno za testiranje naših poslužiteljskih arhitektura.
  • nginx.unixism.net: Ponekad želimo pokrenuti više od jedne instance poslužiteljskog programa. Da biste to učinili, Nginx poslužitelj s odgovarajućim postavkama radi kao balanser opterećenja koji dolazi iz ab procesima našeg poslužitelja.
  • zerohttpd.unixism.net: Ovdje pokrećemo naše poslužiteljske programe na sedam različitih arhitektura, jednu po jednu.
  • redis.unixism.net: Ovaj poslužitelj pokreće Redis demon, gdje se pohranjuju unosi u knjigu gostiju i brojači posjetitelja.

Svi poslužitelji rade na istoj jezgri procesora. Ideja je procijeniti maksimalnu izvedbu svake arhitekture. Budući da se svi poslužiteljski programi testiraju na istom hardveru, ovo je osnova za usporedbu. Moja postavka za testiranje sastoji se od virtualnih poslužitelja iznajmljenih od Digital Oceana.

Što mjerimo?

Možete mjeriti različite pokazatelje. Procjenjujemo izvedbu svake arhitekture u danoj konfiguraciji učitavanjem poslužitelja sa zahtjevima na različitim razinama paralelizma: opterećenje raste s 20 na 15 000 istodobnih korisnika.

Rezultati ispitivanja

Sljedeći grafikon prikazuje performanse poslužitelja na različitim arhitekturama na različitim razinama paralelizma. Y-os je broj zahtjeva u sekundi, x-os su paralelne veze.

Izvedba Linux mrežne aplikacije. Uvod

Izvedba Linux mrežne aplikacije. Uvod

Izvedba Linux mrežne aplikacije. Uvod

U nastavku je tablica s rezultatima.

zahtjeva u sekundi

paralelizam
iterativni
vilica
prethodna vilica
strujanje
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
veliko širenje
2138

5000
-
veliko širenje
1600
1100
2519
-
2235

8000
-
-
1200
veliko širenje
2451
-
2100

10
-
-
veliko širenje
-
2200
-
2200

11
-
-
-
-
2200
-
2122

12
-
-
-
-
970
-
1958

13
-
-
-
-
730
-
1897

14
-
-
-
-
590
-
1466

15
-
-
-
-
532
-
1281

Iz grafikona i tablice vidljivo je da iznad 8000 istovremenih zahtjeva imamo još samo dva igrača: pre-fork i epoll. Kako se opterećenje povećava, poslužitelj koji se temelji na anketi radi lošije od poslužitelja za strujanje. Arhitektura prethodnog stvaranja niti je vrijedan konkurent epollu, dokaz koliko dobro Linux kernel raspoređuje veliki broj niti.

ZeroHTTPd izvorni kod

ZeroHTTPd izvorni kod здесь. Za svaku arhitekturu postoji 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 └── predlošci └── knjiga gostiju └── index.html

Uz sedam direktorija za sve arhitekture, u direktoriju najviše razine postoje još dva: public i templates. Prvi sadrži datoteku index.html i sliku s prve snimke zaslona. Tamo možete staviti druge datoteke i mape, a ZeroHTTPd bi te statične datoteke trebao poslužiti bez problema. Ako put u pregledniku odgovara putu u javnoj mapi, tada ZeroHTTPd traži datoteku index.html u ovom direktoriju. Sadržaj za knjigu gostiju generira se dinamički. Ima samo početnu stranicu, a sadržaj se temelji na datoteci 'templates/guestbook/index.html'. ZeroHTTPd jednostavno dodaje dinamičke stranice za proširenje. Ideja je da korisnici mogu dodati predloške u ovaj direktorij i po potrebi proširiti ZeroHTTPd.

Za izgradnju svih sedam poslužitelja, pokrenite make all iz direktorija najviše razine - i sve će se verzije pojaviti u ovom direktoriju. Izvršne datoteke traže direktorije public i templates u direktoriju iz kojeg su pokrenute.

Linux API

Ne morate biti dobro upućeni u Linux API da biste razumjeli informacije u ovoj seriji članaka. Ipak, preporučam da pročitate više o ovoj temi; postoji mnogo referentnih izvora na Internetu. Iako ćemo se dotaknuti nekoliko kategorija Linux API-ja, naš fokus bit će prvenstveno na procesima, nitima, događajima i mrežnom stogu. Uz knjige i članke o Linux API-ju, također preporučujem čitanje mana za sistemske pozive i korištene funkcije knjižnice.

Izvedba i skalabilnost

Jedna napomena o performansama i skalabilnosti. Teoretski, među njima nema veze. Možete imati web uslugu koja radi vrlo dobro, s vremenom odgovora od nekoliko milisekundi, ali se uopće ne skalira. Isto tako, može postojati web aplikacija s lošim performansama kojoj je potrebno nekoliko sekundi da odgovori, ali se skalira za desetke kako bi obradila desetke tisuća istodobnih korisnika. Međutim, kombinacija visokih performansi i skalabilnosti vrlo je moćna kombinacija. Aplikacije visokih performansi općenito štedljivo koriste resurse i tako učinkovito opslužuju više istodobnih korisnika na poslužitelju, smanjujući troškove.

CPU i I/O zadaci

Konačno, u računalstvu uvijek postoje dvije moguće vrste zadataka: za I/O i CPU. Primanje zahtjeva preko Interneta (mrežni I/O), posluživanje datoteka (mrežni i disk I/O), komunikacija s bazom podataka (mrežni i disk I/O) sve su I/O aktivnosti. Neki upiti baze podataka mogu biti malo intenzivni za CPU (sortiranje, usrednjavanje milijun rezultata, itd.). Većina web aplikacija ograničena je najvećim mogućim I/O, a procesor se rijetko koristi punim kapacitetom. Kada vidite da neki I/O zadatak koristi puno CPU-a, to je najvjerojatnije znak loše arhitekture aplikacije. To može značiti da se CPU resursi troše na upravljanje procesima i prebacivanje konteksta - a to nije sasvim korisno. Ako radite nešto poput obrade slika, pretvorbe audio datoteka ili strojnog učenja, aplikacija zahtijeva snažne CPU resurse. Ali za većinu aplikacija to nije slučaj.

Saznajte više o arhitekturama poslužitelja

  1. Dio I: Iterativna arhitektura
  2. Dio II. Fork poslužitelji
  3. Dio III. Pre-fork poslužitelji
  4. Dio IV. Poslužitelji s nitima izvršenja
  5. Dio V. Pre-threaded poslužitelji
  6. Dio VI. Arhitektura temeljena na pol
  7. Dio VII. arhitektura temeljena na epoll-u

Izvor: www.habr.com

Dodajte komentar