Zmogljivost omrežnih aplikacij Linux. Uvod

Spletne aplikacije se danes uporabljajo povsod, med vsemi transportnimi protokoli pa HTTP prevladuje. Pri raziskovanju podrobnosti razvoja spletnih aplikacij večina zelo malo pozornosti posveti operacijskemu sistemu, kjer se te aplikacije dejansko izvajajo. Ločevanje razvoja (Dev) in delovanja (Ops) je le poslabšalo situacijo. Vendar pa z naraščanjem kulture DevOps razvijalci začnejo prevzemati odgovornost za zagon svojih aplikacij v oblaku, zato je zanje zelo koristno, da se podrobno seznanijo z ozadjem operacijskega sistema. To je še posebej koristno, če poskušate vzpostaviti sistem za tisoče ali deset tisoč sočasnih povezav.

Omejitve v spletnih storitvah so zelo podobne omejitvam v drugih aplikacijah. Ne glede na to, ali gre za ravnotežne obremenitve ali strežnike baz podatkov, imajo vse te aplikacije podobne težave v visokozmogljivem okolju. Razumevanje teh osnovnih omejitev in načinov za njihovo premagovanje vam bo omogočilo oceno zmogljivosti in razširljivosti vaših spletnih aplikacij.

To serijo člankov pišem kot odgovor na vprašanja mladih razvijalcev, ki želijo postati dobro obveščeni sistemski arhitekti. Nemogoče je jasno razumeti metode optimizacije aplikacij Linux, ne da bi se poglobili v osnove njihovega delovanja na ravni operacijskega sistema. Čeprav obstaja veliko vrst aplikacij, v tem ciklu želim raziskati mrežne aplikacije, ne namiznih, kot so brskalniki ali urejevalniki besedil. Ta material je namenjen razvijalcem in arhitektom, ki želijo razumeti, kako delujejo programi Linux ali Unix ter kako jih strukturirati za visoko zmogljivost.

Linux je strežni operacijski sistem, in najpogosteje vaše aplikacije delujejo prav na tej OS. Čeprav govorim "Linux", lahko večino časa z gotovostjo domnevate, da imam v mislih vse Unix-podobne operacijske sisteme na splošno. Kljub temu koda, ki jo spremljam, ni bila testirana na drugih sistemih. Zato, če vas zanima FreeBSD ali OpenBSD, se lahko rezultati razlikujejo. Ko poskusim kaj specifičnega za Linux, to jasno označim.

Čeprav lahko pridobljeno znanje uporabite za razvoj aplikacije od osnov, ki bo odlično optimizirana, je bolje, da tega ne storite. Če napišete nov spletni strežnik v C ali C++ za poslovno aplikacijo vaše organizacije, bi lahko to bil vaš zadnji dan na delu. Kljub temu vam znanje strukture teh aplikacij lahko pomaga pri izbiri že obstoječih programov. Lahko primerjate sisteme na osnovi procesov s sistemi na osnovi niti, prav tako kot tiste, ki temeljijo na dogodkih. Razumeli boste in cenili, zakaj Nginx deluje bolje kot Apache httpd, zakaj Pythonova aplikacija na osnovi Tornado lahko obravnava več uporabnikov v primerjavi s Pythonovo aplikacijo na osnovi Django.

ZeroHTTPd: učni pripomoček

ZeroHTTPd je spletni strežnik, ki sem ga napisal od osnov s C kot učni pripomoček. Nima zunanjih odvisnosti, vključno z dostopom do Redis. Zagonimo lastne Redis postopke. Več podrobnosti si oglejte spodaj.

Čeprav bi lahko dolgo razpravljali o teoriji, ni nič boljšega, kot pisanje kode, njeno zagon in primerjava vseh arhitektur strežnikov. To je najbolj očiten način. Zato bomo pisali preprost spletni strežnik ZeroHTTPd, ki bo uporabljal vsak model: temelječ na procesih, threadih in dogodkih. Preverili bomo vsakega od teh strežnikov in pogledali, kako delujejo v primerjavi drug z drugim. ZeroHTTPd je implementiran v eni C datoteki. Strežnik na osnovi dogodkov vključuje uthash, odlična implementacija hash tabele, ki prihaja v eni glavni datoteki. V drugih primerih ni dodatnih odvisnosti, da ne bi zapletali projekta.

V kodi je veliko komentarjev, da bi pomagali razumeti. Kot preprost spletni strežnik v nekaj vrsticah kode, ZeroHTTPd predstavlja tudi minimalni okvir za spletni razvoj. Ima omejeno funkcionalnost, vendar je sposoben služiti statične datoteke in zelo preproste "dinamične" strani. Moram reči, da je ZeroHTTPd odličen za učenje, kako ustvarjati visoko performantne Linux aplikacije. Na splošno, večina spletnih storitev čaka na zahteve, jih preverja in obravnava. Točno to bo ZeroHTTPd počel. Je učni pripomoček, ne pa instrument za produkcijo. Ni močan pri obravnavi napak in ima malo najboljših praks varnosti (oh ja, uporabil sem strcpy) ali z zapletenimi triki jezika C. A upam, da bo dobro opravil svojo nalogo.

Zmogljivost omrežnih aplikacij Linux. Uvod
Začetna stran ZeroHTTPd. Lahko posreduje različne vrste datotek, vključno z slikami

Aplikacija gostinske knjige

Sodobne spletne aplikacije običajno niso omejene na statične datoteke. Imajo kompleksne interakcije z različnimi BDP-ji, predpomnilniki itd. Zato bomo ustvarili preprosto spletno aplikacijo z imenom 'Gostinska knjiga', kjer obiskovalci pustijo zapise pod svojimi imeni. V gostinski knjigi so shranjeni prejšnji zapisi. Na dnu strani je prav tako števec obiskovalcev.

Zmogljivost omrežnih aplikacij Linux. Uvod
Spletna aplikacija 'Gostinska knjiga' ZeroHTTPd

Števec obiskovalcev in zapisi gostinske knjige se shranjujejo v Redis. Za komunikacijo z Redisom so implementirani lastni postopki, ki ne odvisijo od zunanjih knjižnic. Nisem velik oboževalec razvoja lastne kode, ko so na voljo javna in dobro testirana rešitev. A cilj ZeroHTTPd je raziskati zmogljivost Linuxa in dostop do zunanjih storitev, medtem ko vzdrževanje HTTP zahtevkov resno vpliva na zmogljivost. Moramo popolnoma nadzorovati komunikacijo z Redisom v vsaki naši strežniški arhitekturi. V eni arhitekturi uporabljamo blokirajoče klice, v drugih pa postopke temelječe na dogodkih. Uporaba zunanje odjemalske knjižnice Redis ne bi dala takšnega nadzora. Poleg tega naš mali odjemalec Redis izvaja le nekaj funkcij (pridobivanje, nastavljanje in povečanje ključa; pridobivanje in dodajanje v tabelo). Prav tako je protokol Redis izjemno eleganten in preprost. Učiti se ga ni treba posebej. Samo dejstvo, da celotno delo protokol opravlja v približno sto vrsticah kode, kaže, kako dobro je zasnovan.

Na naslednji sliki so prikazane dejavnosti aplikacije, ko odjemalec (brskalnik) pošlje zahtevo /guestbookURL.

Zmogljivost omrežnih aplikacij Linux. Uvod
Mehanizem delovanja aplikacije gostinske knjige

Ko zaman da treba prikazati stranicu knjige gostiju, dolazi do jednog poziva datotečnom sistemu za učitavanje šablona u memoriju i tri mrežna poziva prema Redis-u. Datoteka šablona sadrži većinu HTML sadržaja za stranicu na gornjoj slici. Tu su takođe i posebni placeholderi za dinamički deo sadržaja: unose i broj posetilaca. Dobijamo ih iz Redis-a, umetnemo na stranicu i isporučujemo klijentu potpuno formirani sadržaj. Treći poziv prema Redis-u može se izbeći, jer Redis vraća novu vrednost ključa prilikom povećanja. Međutim, za naš server sa asinkronom arhitekturom zasnovanom na događajima, mnoštvo mrežnih poziva je dobro iskušenje u obrazovne svrhe. Stoga odbacujemo vraćenu vrednost Redis-a o broju posetilaca i zahtevamo je odvojenim pozivom.

Serverne arhitekture ZeroHTTPd

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

  • Iterativna
  • Fork server (jedan podproces po zahtevu)
  • Pre-fork server (prethodno forkovanje procesa)
  • Server sa izvršnim nitima (jedna nit po zahtevu)
  • Server sa prethodno kreiranim nitima
  • Arhitektura zasnovana na poll()
  • Arhitektura zasnovana na epoll

Mjerimo performanse svake arhitekture opterećujući server HTTP zahtevima. No, prilikom upoređivanja arhitektura sa visokom paralelizmom, broj zahteva se povećava. Testiramo tri puta i računamo prosek.

Metodologija testiranja

Zmogljivost omrežnih aplikacij Linux. Uvod
Podešavanje za opterećujuće testiranje ZeroHTTPd

Važno je da tokom izvođenja testova svi komponenti ne rade na jednoj mašini. U tom slučaju, operativni sistem nosi dodatne troškove planiranja, jer se komponente takmiče za CPU. Merenje troškova operativnog sistema sa svake od odabranih servernih arhitektura je jedan od najvažnijih ciljeva ove vežbe. Dodavanje većeg broja varijabli postat će štetno za proces. Stoga, podešavanje prikazano na slici iznad najbolje funkcioniše.

Šta radi svaki od ovih servera

  • load.unixism.net: ovde pokrećemo ab, Apache Benchmark alat. On generiše opterećenje potrebno za testiranje naših servernih arhitektura.
  • nginx.unixism.net: včasih želimo zagnati več kot en izvod strežniškega programa. Za to strežnik Nginx s primernimi nastavitvami deluje kot uravnoteževalec obremenitev, ki prihaja od ab naše strežniške procese.
  • zerohttpd.unixism.net: tukaj zagnamo naše strežniške programe na sedmih različnih arhitekturah, po enega naenkrat.
  • redis.unixism.net: na tem strežniku deluje demon Redis, kjer so shranjeni zapisi v knjigi gostov in števec obiskovalcev.

Vsi strežniki delujejo na enem procesorskem jedru. Ideja je oceniti maksimalno zmogljivost posameznih arhitektur. Ker se vsi strežniški programi testirajo na isti opremi, je to osnovna raven za njihovo primerjavo. Moja testna nastavitev je sestavljena iz virtualnih strežnikov, najetih pri Digital Ocean.

Kaj merimo?

Lahko izmerimo različne kazalnike. Ocenjujemo zmogljivost vsake arhitekture v tej konfiguraciji, tako da obremenjujemo strežnike z zahtevami na različnih ravneh paralelizma: obremenitev narašča od 20 do 15 000 hkratnih uporabnikov.

Výsledky testů

Na naslednjem diagramu je prikazana zmogljivost strežnikov na različnih arhitekturah pri različnih ravneh paralelizma. Na osi y je število zahtevkov na sekundo, na osi x pa paralelne povezave.

Zmogljivost omrežnih aplikacij Linux. Uvod

Zmogljivost omrežnih aplikacij Linux. Uvod

Zmogljivost omrežnih aplikacij Linux. Uvod

Spodaj je tabela z rezultati.

zahtevkov na sekundo

paralelizem
iterativni
fork
pred-fork
tudenjski
pred-tudenjski
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
veliko razpršenosti
2138

5000
–
veliko razpršenosti
1600
1100
2519
–
2235

8000
–
–
1200
veliko razpršenosti
2451
–
2100

10 000
–
–
veliko razpršenosti
–
2200
–
2200

11 000
–
–
–
–
2200
–
2122

12 000
–
–
–
–
970
–
1958

13 000
–
–
–
–
730
–
1897

14 000
–
–
–
–
590
–
1466

15 000
–
–
–
–
532
–
1281

Iz grafikona in tabele je razvidno, da pri več kot 8000 hkratnih zahtevkov ostaneta le dva igralca: pred-fork in epoll. Z naraščanjem obremenitve strežnik na osnovi poll deluje slabše kot tudenjski. Arhitektura s predhodnim ustvarjanjem niti predstavlja dostojno konkurenco epoll: to priča o tem, kako dobro jedro Linux načrtuje veliko število niti.

Izvorna koda ZeroHTTPd

Izvorna koda ZeroHTTPd ovde. Za vsako arhitekturo je posebej imenik.

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.html

Poleg sedmih direktorijev za vse arhitekture, v zgornjem imeniku sta še dve: public in templates. V prvi je datoteka index.html in slika iz prvega posnetka zaslona. Tja lahko postavite druge datoteke in mape, ZeroHTTPd pa bi brez težav izdal te statične datoteke. Če se pot v brskalniku ujema s potjo v mapi public, ZeroHTTPd išče v tem imeniku datoteko index.html. Vsebina za gostinsko knjigo se dinamično generira. Ima samo glavno stran, njena vsebina pa temelji na datoteki 'templates/guestbook/index.html'. V ZeroHTTPd je enostavno dodati dinamične strani za razširitev. Ideja je, da lahko uporabniki v to mapo dodajajo predloge in razširjajo ZeroHTTPd po potrebi.

Za sestavljanje vseh sedmih strežnikov zaženite make all iz zgornjega imenika — in vsi gradniki se bodo pojavili v tem imeniku. Izvedljive datoteke iščejo imenike public in templates v tistem imeniku, iz katerega so zagnane.

Linux API

Da bi razumeli informacije v tem ciklu člankov, ni nujno, da dobro obvladate Linux API. Kljub temu priporočam, da preberete več o tej temi; na spletu je veliko referenčnih virov. Čeprav se bomo dotaknili več kategorij Linux API, se bomo osredotočili predvsem na procese, niti, dogodke in mrežni sklad. Poleg knjig in člankov o Linux API priporočam tudi, da preberete menije za sistemske klice in uporabljene knjižnične funkcije.

Učinkovitost in razširljivost

Ena opomba o učinkovitosti in razširljivosti. Teoretično med njima ni nobene povezave. Imate lahko spletno storitev, ki deluje zelo dobro, z odzivnim časom v nekaj milisekundah, a se sploh ne razširja. Enako lahko imate slabo delujočo spletno aplikacijo, ki potrebuje nekaj sekund za odgovor, a se razširja na desetine za obvladovanje desetih tisoč sočasnih uporabnikov. Kljub temu pa je kombinacija visoke učinkovitosti in razširljivosti zelo močna kombinacija. Visoko učinkovite aplikacije na splošno varčno uporabljajo vire in tako učinkovito obravnavajo več sočasnih uporabnikov na strežniku, kar zmanjšuje stroške.

Naloge CPU in I/O

Na koncu že obstajata dva možna tipa nalog v izračunih: za I/O in CPU. Sprejemanje zahtevkov prek interneta (omrežni vhod-izhod), upravljanje datotek (omrežni in diskovni vhod-izhod), komunikacije z bazo podatkov (omrežni in diskovni vhod-izhod) — vse to so I/O dejanja. Nekateri zahtevki za bazo podatkov lahko nekoliko obremenijo CPU (sortiranje, izračun povprečja milijona rezultatov itd.). Večina spletnih aplikacij je omejena glede na največji možni I/O, medtem ko se procesor redko uporablja na polno moč. Ko opazite, da neka naloga vhod-izhod uporablja veliko CPU, je verjetno to znak slabe arhitekture aplikacije. To lahko pomeni, da se CPU viri porabljajo za upravljanje procesov in preklapljanje kontekstov — kar ni povsem koristno. Če izvajate naloge, kot so obdelava slik, pretvorba avdio datotek ali strojno učenje, potem aplikacija potrebuje močne CPU vire. Toda za večino aplikacij temu ni tako.

Podrobneje o strežniških arhitekturah

  1. Del I. Iterativna arhitektura
  2. Del II. Fork strežniki
  3. Del III. Pre-fork strežniki
  4. Del IV. Strežniki s tremi izvedbenimi nitmi
  5. Del V. Strežniki s predhodnim ustvarjanjem niti
  6. Del VI. Arhitektura, ki temelji na poll
  7. Del VII. Arhitektura, ki temelji na epoll

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster