Performanca e aplikacionit të rrjetit Linux. Prezantimi

Aplikacionet në ueb përdoren tani kudo dhe midis të gjitha protokolleve të transportit, HTTP zë pjesën e luanit. Kur studiojnë nuancat e zhvillimit të aplikacioneve në internet, shumica e njerëzve i kushtojnë shumë pak vëmendje sistemit operativ ku funksionojnë këto aplikacione. Ndarja e zhvillimit (Dev) dhe operacioneve (Ops) vetëm sa e përkeqësoi situatën. Por me rritjen e kulturës DevOps, zhvilluesit po bëhen përgjegjës për ekzekutimin e aplikacioneve të tyre në cloud, kështu që është shumë e dobishme që ata të njihen plotësisht me backend-in e sistemit operativ. Kjo është veçanërisht e dobishme nëse po përpiqeni të vendosni një sistem për mijëra ose dhjetëra mijëra lidhje të njëkohshme.

Kufizimet në shërbimet e internetit janë shumë të ngjashme me ato në aplikacionet e tjera. Qoftë balancuesit e ngarkesës ose serverët e bazës së të dhënave, të gjitha këto aplikacione kanë probleme të ngjashme në një mjedis me performancë të lartë. Të kuptuarit e këtyre kufizimeve themelore dhe si t'i kapërceni ato në përgjithësi do t'ju ndihmojë të vlerësoni performancën dhe shkallëzueshmërinë e aplikacioneve tuaja në internet.

Po shkruaj këtë seri artikujsh në përgjigje të pyetjeve nga zhvilluesit e rinj që duan të bëhen arkitektë sistemesh të mirëinformuar. Është e pamundur të kuptohen qartë teknikat e optimizimit të aplikacioneve Linux pa u zhytur në bazat se si funksionojnë ato në nivelin e sistemit operativ. Edhe pse ka shumë lloje aplikacionesh, në këtë seri unë dua të eksploroj aplikacione të bazuara në ueb dhe jo aplikacione desktopi si shfletuesi ose redaktuesi i tekstit. Ky material është menduar për zhvilluesit dhe arkitektët që duan të kuptojnë se si funksionojnë programet Linux ose Unix dhe si t'i strukturojnë ato për performancë të lartë.

Linux është dhoma e serverit sistemi operativ dhe më shpesh aplikacionet tuaja funksionojnë në këtë OS. Megjithëse them "Linux", shumicën e kohës mund të supozoni me siguri se nënkuptoj të gjitha sistemet operative të ngjashme me Unix në përgjithësi. Megjithatë, unë nuk e kam testuar kodin shoqërues në sisteme të tjera. Pra, nëse jeni të interesuar për FreeBSD ose OpenBSD, rezultatet tuaja mund të ndryshojnë. Kur provoj diçka specifike për Linux, e vë në dukje.

Ndërsa mund ta përdorni këtë njohuri për të ndërtuar një aplikacion nga e para dhe ai do të jetë i optimizuar në mënyrë perfekte, është më mirë të mos e bëni këtë. Nëse shkruani një server të ri ueb në C ose C++ për aplikacionin e biznesit të organizatës suaj, kjo mund të jetë dita juaj e fundit në punë. Megjithatë, njohja e strukturës së këtyre aplikacioneve do të ndihmojë në zgjedhjen e programeve ekzistuese. Ju do të jeni në gjendje të krahasoni sistemet e bazuara në procese me sistemet e bazuara në fije, si dhe ato të bazuara në ngjarje. Do të kuptoni dhe vlerësoni pse Nginx performon më mirë se Apache httpd, pse një aplikacion Python i bazuar në Tornado mund t'u shërbejë më shumë përdoruesve në krahasim me një aplikacion Python të bazuar në Django.

ZeroHTTPd: Mjeti i të mësuarit

ZeroHTTPd është një server në internet që e kam shkruar nga e para në C si një mjet mësimor. Nuk ka varësi të jashtme, duke përfshirë aksesin në Redis. Ne kryejmë procedurat tona Redis. Shihni më poshtë për më shumë detaje.

Edhe pse mund të diskutonim gjerësisht teorinë, nuk ka asgjë më të mirë se të shkruani kodin, ta ekzekutoni atë dhe të krahasoni të gjitha arkitekturat e serverëve me njëra-tjetrën. Kjo është metoda më e dukshme. Prandaj, ne do të shkruajmë një server të thjeshtë ueb ZeroHTTPd duke përdorur çdo model: i bazuar në proces, i bazuar në fije dhe i bazuar në ngjarje. Le të kontrollojmë secilin prej këtyre serverëve dhe të shohim se si performojnë ata në krahasim me njëri-tjetrin. ZeroHTTPd zbatohet në një skedar të vetëm C. Serveri i bazuar në ngjarje përfshin uthash, një zbatim i shkëlqyer i tabelës hash që vjen në një skedar të vetëm kokë. Në raste të tjera, nuk ka varësi, për të mos e komplikuar projektin.

Ka shumë komente në kod për t'ju ndihmuar të kuptoni. Duke qenë një server i thjeshtë në internet në disa rreshta kodi, ZeroHTTPd është gjithashtu një kornizë minimale për zhvillimin e uebit. Ka funksionalitet të kufizuar, por është në gjendje të shërbejë skedarë statikë dhe faqe shumë të thjeshta "dinamike". Më duhet të them se ZeroHTTPd është i mirë për të mësuar se si të krijoni aplikacione Linux me performancë të lartë. Në përgjithësi, shumica e shërbimeve të uebit presin kërkesa, i kontrollojnë dhe i përpunojnë ato. Kjo është pikërisht ajo që ZeroHTTPd do të bëjë. Ky është një mjet për të mësuar, jo për prodhim. Nuk është i mirë në trajtimin e gabimeve dhe nuk ka gjasa të mburret me praktikat më të mira të sigurisë (oh po, kam përdorur strcpy) ose truket e zgjuara të gjuhës C. Por shpresoj që ta bëjë mirë punën e saj.

Performanca e aplikacionit të rrjetit Linux. Prezantimi
Faqja kryesore ZeroHTTPd. Mund të nxjerrë lloje të ndryshme skedarësh duke përfshirë imazhe

Aplikimi i librit të të ftuarve

Aplikacionet moderne në internet zakonisht nuk kufizohen në skedarë statikë. Ata kanë ndërveprime komplekse me baza të ndryshme të dhënash, memorie të fshehta, etj. Pra, ne do të krijojmë një aplikacion të thjeshtë ueb të quajtur "Libri i të ftuarve" ku vizitorët lënë shënime nën emrat e tyre. Regjistrimet e librave të ftuar të lënë më herët. Ekziston edhe një numërues vizitorësh në fund të faqes.

Performanca e aplikacionit të rrjetit Linux. Prezantimi
Ueb aplikacioni "Libri i të ftuarve" ZeroHTTPd

Numri i vizitorëve dhe shënimet e librit të të ftuarve ruhen në Redis. Për komunikimet me Redis zbatohen procedurat e veta, ato nuk varen nga biblioteka e jashtme. Unë nuk jam një adhurues i madh i nxjerrjes së kodit homebrew kur ka zgjidhje të disponueshme publikisht dhe të testuara mirë. Por qëllimi i ZeroHTTPd është të studiojë performancën e Linux dhe aksesin në shërbimet e jashtme, ndërsa shërbimi i kërkesave HTTP ka një ndikim serioz në performancë. Ne duhet të kontrollojmë plotësisht komunikimet me Redis në secilën prej arkitekturave të serverit tonë. Në disa arkitektura ne përdorim thirrje bllokuese, në të tjera përdorim procedura të bazuara në ngjarje. Përdorimi i një biblioteke të jashtme të klientit Redis nuk do ta sigurojë këtë kontroll. Për më tepër, klienti ynë i vogël Redis kryen vetëm disa funksione (marrja, vendosja dhe rritja e një çelësi; marrja dhe shtimi në një grup). Për më tepër, protokolli Redis është jashtëzakonisht elegant dhe i thjeshtë. Ju as nuk keni nevojë ta mësoni atë posaçërisht. Vetë fakti që protokolli bën të gjithë punën në rreth njëqind rreshta kodi tregon se sa mirë është i menduar.

Figura e mëposhtme tregon se çfarë bën aplikacioni kur klienti (shfletuesi) kërkon /guestbookURL.

Performanca e aplikacionit të rrjetit Linux. Prezantimi
Si funksionon aplikacioni i librit të të ftuarve

Kur duhet të lëshohet një faqe e librit të të ftuarve, bëhet një thirrje në sistemin e skedarëve për të lexuar shabllonin në memorie dhe tre thirrje rrjeti në Redis. Skedari i shabllonit përmban shumicën e përmbajtjes HTML për faqen në pamjen e mësipërme. Ekzistojnë gjithashtu mbajtëse të veçanta për pjesën dinamike të përmbajtjes: postimet dhe numëruesi i vizitorëve. Ne i marrim nga Redis, i futim në faqe dhe i ofrojmë klientit përmbajtje të formuar plotësisht. Thirrja e tretë në Redis mund të shmanget sepse Redis kthen vlerën e re të çelësit kur rritet. Megjithatë, për serverin tonë, i cili ka një arkitekturë asinkrone të bazuar në ngjarje, shumë thirrje në rrjet janë një test i mirë për qëllime mësimore. Pra, ne hedhim vlerën e kthimit të Redis të numrit të vizitorëve dhe e kërkojmë atë me një thirrje të veçantë.

Arkitekturat e serverit ZeroHTTPd

Ne po ndërtojmë shtatë versione të ZeroHTTPd me të njëjtin funksionalitet, por arkitektura të ndryshme:

  • Përsëritëse
  • Serveri fork (një proces fëmijë për çdo kërkesë)
  • Serveri para pirunit (para-forkimi i proceseve)
  • Server me fije ekzekutimi (një fill për kërkesë)
  • Server me krijimin e para-thread
  • Bazuar në arkitekturë poll()
  • Bazuar në arkitekturë epoll

Ne matim performancën e secilës arkitekturë duke ngarkuar serverin me kërkesa HTTP. Por kur krahasohen arkitekturat shumë paralele, numri i pyetjeve rritet. Ne testojmë tre herë dhe llogarisim mesataren.

Metodologjia e testimit

Performanca e aplikacionit të rrjetit Linux. Prezantimi
Konfigurimi i testimit të ngarkesës ZeroHTTPd

Është e rëndësishme që gjatë ekzekutimit të testeve, të gjithë komponentët të mos funksionojnë në të njëjtën makinë. Në këtë rast, OS ka shpenzime shtesë të planifikimit pasi komponentët konkurrojnë për CPU. Matja e ngarkesës së sistemit operativ të secilës prej arkitekturave të zgjedhura të serverit është një nga qëllimet më të rëndësishme të këtij ushtrimi. Shtimi i më shumë variablave do të bëhet i dëmshëm për procesin. Prandaj, cilësimi në foton e mësipërme funksionon më së miri.

Çfarë bën secili prej këtyre serverëve?

  • load.unixism.net: Këtu vrapojmë ab, shërbimi Apache Benchmark. Ai gjeneron ngarkesën e nevojshme për të testuar arkitekturat e serverit tonë.
  • nginx.unixism.net: Ndonjëherë duam të ekzekutojmë më shumë se një shembull të një programi serveri. Për ta bërë këtë, serveri Nginx me cilësimet e duhura funksionon si një balancues i ngarkesës që vjen nga ab në proceset e serverit tonë.
  • zerohttpd.unixism.net: Këtu ne ekzekutojmë programet tona të serverit në shtatë arkitektura të ndryshme, një nga një.
  • redis.unixism.net: Ky server drejton demonin Redis, ku ruhen hyrjet e librit të të ftuarve dhe numëruesit e vizitorëve.

Të gjithë serverët funksionojnë në të njëjtën bërthamë procesori. Ideja është të vlerësohet performanca maksimale e secilës arkitekturë. Meqenëse të gjitha programet e serverëve testohen në të njëjtin harduer, kjo është një bazë për krahasim. Konfigurimi im i provës përbëhet nga serverë virtualë të marrë me qira nga Digital Ocean.

Çfarë po matim?

Ju mund të matni tregues të ndryshëm. Ne vlerësojmë performancën e secilës arkitekturë në një konfigurim të caktuar duke ngarkuar serverët me kërkesa në nivele të ndryshme paralelizmi: ngarkesa rritet nga 20 në 15 përdorues të njëkohshëm.

Rezultatet e provës

Grafiku i mëposhtëm tregon performancën e serverëve në arkitektura të ndryshme në nivele të ndryshme paralelizmi. Boshti y është numri i kërkesave për sekondë, boshti x është lidhje paralele.

Performanca e aplikacionit të rrjetit Linux. Prezantimi

Performanca e aplikacionit të rrjetit Linux. Prezantimi

Performanca e aplikacionit të rrjetit Linux. Prezantimi

Më poshtë është një tabelë me rezultatet.

kërkesa për sekondë

paralelizëm
përsëritëse
pirun
para-pirun
transmetimi
transmetim paraprak
sondazh
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
përhapje e madhe
2138

5000
-
përhapje e madhe
1600
1100
2519
-
2235

8000
-
-
1200
përhapje e madhe
2451
-
2100

10
-
-
përhapje e madhe
-
2200
-
2200

11
-
-
-
-
2200
-
2122

12
-
-
-
-
970
-
1958

13
-
-
-
-
730
-
1897

14
-
-
-
-
590
-
1466

15
-
-
-
-
532
-
1281

Nga grafiku dhe tabela shihet se mbi 8000 kërkesa të njëkohshme na kanë mbetur vetëm dy lojtarë: pre-fork dhe epoll. Ndërsa ngarkesa rritet, një server i bazuar në sondazhe funksionon më keq se ai i transmetimit. Arkitektura e para-krijimit të fillit është një konkurrent i denjë për epoll, një dëshmi se sa mirë kerneli Linux planifikon një numër të madh thread-sh.

Kodi burimor ZeroHTTPd

Kodi burimor ZeroHTTPd këtu. Ekziston një drejtori e veçantë për secilën arkitekturë.

ZeroHTTPd │ ├── 01_iterative │ ├── main.c ├── 02_forking │ ├── main.c ├── 03_preforking ├──. 04_ filetim │ ├── kryesore.c ├── 05_prethreading │ ├── main.c ├── 06_poll │ ├── main.c ├── 07_epoll │ └─├ └──├─── Kryesor.c ─ ├── index .html │ └── tux . png └── shabllone └── libri i të ftuarve └── index.html

Përveç shtatë drejtorive për të gjitha arkitekturat, ka edhe dy të tjera në drejtorinë e nivelit të lartë: publike dhe shabllone. E para përmban skedarin index.html dhe imazhin nga pamja e parë e ekranit. Mund të vendosni skedarë dhe dosje të tjera atje, dhe ZeroHTTPd duhet t'i shërbejë ato skedarë statikë pa asnjë problem. Nëse shtegu në shfletues përputhet me shtegun në dosjen publike, atëherë ZeroHTTPd kërkon skedarin index.html në këtë direktori. Përmbajtja për librin e të ftuarve krijohet në mënyrë dinamike. Ajo ka vetëm një faqe kryesore dhe përmbajtja e saj bazohet në skedarin 'templates/guestbook/index.html'. ZeroHTTPd shton lehtësisht faqe dinamike për zgjerim. Ideja është që përdoruesit mund të shtojnë shabllone në këtë direktori dhe të zgjerojnë ZeroHTTPd sipas nevojës.

Për të ndërtuar të shtatë serverët, ekzekutoni make all nga drejtoria e nivelit të lartë - dhe të gjitha ndërtimet do të shfaqen në këtë direktori. Skedarët e ekzekutueshëm kërkojnë drejtoritë publike dhe shabllonet në drejtorinë nga e cila janë nisur.

Linux API

Ju nuk keni nevojë të jeni të aftë për Linux API për të kuptuar informacionin në këtë seri artikujsh. Sidoqoftë, unë rekomandoj të lexoni më shumë për këtë temë; ka shumë burime referimi në internet. Edhe pse do të prekim disa kategori të API-ve Linux, fokusi ynë do të jetë kryesisht në proceset, thread-et, ngjarjet dhe grupin e rrjetit. Përveç librave dhe artikujve rreth Linux API, unë rekomandoj gjithashtu leximin e mana për thirrjet e sistemit dhe funksionet e bibliotekës së përdorur.

Performanca dhe shkallëzueshmëria

Një shënim në lidhje me performancën dhe shkallëzueshmërinë. Teorikisht, nuk ka asnjë lidhje mes tyre. Mund të keni një shërbim në internet që funksionon shumë mirë, me një kohë përgjigjeje prej disa milisekondash, por nuk përshkallëzohet fare. Po kështu, mund të ketë një aplikacion uebi me performancë të dobët që kërkon disa sekonda për t'u përgjigjur, por ai zvogëlohet me dhjetëra për të trajtuar dhjetëra mijëra përdorues të njëkohshëm. Megjithatë, kombinimi i performancës së lartë dhe shkallëzueshmërisë është një kombinim shumë i fuqishëm. Aplikacionet me performancë të lartë në përgjithësi përdorin burimet me kursim dhe kështu u shërbejnë me efikasitet më shumë përdoruesve të njëkohshëm në server, duke ulur kostot.

Detyrat e CPU dhe I/O

Së fundi, në informatikë ka gjithmonë dy lloje të mundshme detyrash: për I/O dhe CPU. Marrja e kërkesave përmes internetit (I/O në rrjet), shërbimi i skedarëve (I/O në rrjet dhe disku), komunikimi me bazën e të dhënave (rrjeti dhe I/O në disk) janë të gjitha aktivitetet I/O. Disa pyetje të bazës së të dhënave mund të jenë pak intensive në CPU (renditje, mesatarisht një milion rezultate, etj.). Shumica e aplikacioneve në ueb janë të kufizuara nga maksimumi i mundshëm I/O dhe procesori përdoret rrallë me kapacitet të plotë. Kur shihni se disa detyra I/O po përdorin shumë CPU, ka shumë të ngjarë një shenjë e arkitekturës së dobët të aplikacionit. Kjo mund të nënkuptojë se burimet e CPU-së harxhohen në menaxhimin e procesit dhe ndërrimin e kontekstit - dhe kjo nuk është plotësisht e dobishme. Nëse jeni duke bërë diçka si përpunimi i imazhit, konvertimi i skedarëve audio ose mësimi i makinerive, atëherë aplikacioni kërkon burime të fuqishme CPU. Por për shumicën e aplikacioneve ky nuk është rasti.

Mësoni më shumë rreth arkitekturave të serverëve

  1. Pjesa I: Arkitektura përsëritëse
  2. Pjesa II. Serverët Fork
  3. Pjesa III. Serverët para pirunit
  4. Pjesa IV. Serverë me fije ekzekutimi
  5. Pjesa V. Serverët e filetuar paraprakisht
  6. Pjesa VI. Arkitektura e bazuar në Pol
  7. Pjesa VII. Arkitektura e bazuar në epol

Burimi: www.habr.com

Shto një koment