Linukso-reta aplikaĵo-efikeco. Enkonduko

Retaj aplikaĵoj nun estas uzataj ĉie, kaj inter ĉiuj transportprotokoloj, HTTP okupas la plej grandan parton. Kiam vi studas la nuancojn de disvolvo de TTT-aplikoj, plej multaj homoj tre malmulte atentas la operaciumon, kie ĉi tiuj aplikoj efektive funkcias. La disiĝo de evoluo (Dev) kaj operacioj (Ops) nur plimalbonigis la situacion. Sed kun la kresko de DevOps-kulturo, programistoj iĝas respondecaj pri rulado de siaj aplikoj en la nubo, do estas tre utile ke ili plene koniĝu kun la backend de la operaciumo. Ĉi tio estas precipe utila se vi provas deploji sistemon por miloj aŭ dekoj da miloj da samtempaj konektoj.

La limigoj en retservoj estas tre similaj al tiuj en aliaj aplikoj. Ĉu temas pri ŝarĝbalanciloj aŭ datumbazaj serviloj, ĉiuj ĉi tiuj aplikoj havas similajn problemojn en alt-efikeca medio. Kompreni ĉi tiujn fundamentajn limigojn kaj kiel venki ilin ĝenerale helpos vin taksi la rendimenton kaj skaleblon de viaj TTT-aplikoj.

Mi skribas ĉi tiun serion de artikoloj responde al demandoj de junaj programistoj, kiuj volas fariĝi bone informitaj sistemaj arkitektoj. Estas neeble klare kompreni Linuksajn aplikaĵajn optimumigajn teknikojn sen plonĝi en la bazaĵojn pri kiel ili funkcias ĉe la mastruma sistemo. Kvankam ekzistas multaj specoj de aplikoj, en ĉi tiu serio mi volas esplori ret-bazitajn aplikojn prefere ol labortablaj aplikoj kiel retumilo aŭ tekstredaktilo. Ĉi tiu materialo estas destinita por programistoj kaj arkitektoj, kiuj volas kompreni kiel funkcias Linuksaj aŭ Uniksaj programoj kaj kiel strukturi ilin por alta rendimento.

Linukso estas servila ĉambro operaciumo, kaj plej ofte viaj aplikaĵoj funkcias per ĉi tiu OS. Kvankam mi diras "Linukso", plejofte vi povas sekure supozi, ke mi celas ĉiujn Unikso-similajn operaciumojn ĝenerale. Tamen mi ne testis la akompanan kodon en aliaj sistemoj. Do, se vi interesiĝas pri FreeBSD aŭ OpenBSD, viaj rezultoj povas varii. Kiam mi provas ion specifan Linukson, mi atentigas ĝin.

Dum vi povas uzi ĉi tiun scion por konstrui app de nulo kaj ĝi estos perfekte optimumigita, estas plej bone ne fari tion. Se vi skribas novan retservilon en C aŭ C++ por la komerca aplikaĵo de via organizo, ĉi tio eble estos via lasta tago en la laboro. Tamen, koni la strukturon de ĉi tiuj aplikoj helpos elekti ekzistantajn programojn. Vi povos kompari procez-bazitajn sistemojn kun faden-bazitaj sistemoj same kiel okazaĵ-bazitaj. Vi komprenos kaj aprezos kial Nginx funkcias pli bone ol Apache httpd, kial Tornado-bazita Python-apliko povas servi pli da uzantoj kompare kun Django-bazita Python-apliko.

ZeroHTTPd: Lerna Ilo

NuloHTTPd estas retservilo, kiun mi skribis de nulo en C kiel instruilo. Ĝi ne havas eksterajn dependecojn, inkluzive de aliro al Redis. Ni prizorgas niajn proprajn Redis-procedojn. Vidu sube por pliaj detaloj.

Kvankam ni povus longe diskuti teorion, estas nenio pli bona ol skribi kodon, ruli ĝin kaj kompari ĉiujn servilajn arkitekturojn unu kun la alia. Ĉi tiu estas la plej evidenta metodo. Tial, ni skribos simplan ZeroHTTPd retservilon uzante ĉiun modelon: procez-bazita, faden-bazita kaj evento-bazita. Ni kontrolu ĉiun el ĉi tiuj serviloj kaj vidu kiel ili funkcias kompare unu kun la alia. ZeroHTTPd estas efektivigita en ununura C-dosiero. La okazaĵ-bazita servilo inkluzivas uthash, bonega hashtabelefektivigo kiu venas en ununura kapdosiero. En aliaj kazoj, ne ekzistas dependecoj, por ne malfaciligi la projekton.

Estas multaj komentoj en la kodo por helpi vin kompreni. Estante simpla retservilo en kelkaj linioj de kodo, ZeroHTTPd ankaŭ estas minimuma kadro por reto-disvolviĝo. Ĝi havas limigitan funkciecon, sed kapablas servi statikajn dosierojn kaj tre simplajn "dinamikajn" paĝojn. Mi devas diri, ke ZeroHTTPd estas bona por lerni kiel krei alt-efikecajn Linuksajn aplikojn. Ĝenerale, plej multaj retservoj atendas petojn, kontrolas ilin kaj prilaboras ilin. Ĝuste ĉi tio faros ZeroHTTPd. Ĉi tio estas ilo por lernado, ne produktado. Ĝi ne estas bonega pri erartraktado kaj verŝajne ne fanfaronas pri plej bonaj sekurecaj praktikoj (ho ​​jes, mi uzis strcpy) aŭ la lertajn lertaĵojn de la lingvo C. Sed mi esperas, ke ĝi bone plenumas sian laboron.

Linukso-reta aplikaĵo-efikeco. Enkonduko
ZeroHTTPd hejmpaĝo. Ĝi povas eligi malsamajn dosiertipojn inkluzive de bildoj

Apliko de Gastlibro

Modernaj TTT-aplikoj kutime ne estas limigitaj al senmovaj dosieroj. Ili havas kompleksajn interagojn kun diversaj datumbazoj, kaŝmemoroj, ktp. Do ni kreos simplan TTT-aplikaĵon nomitan "Gastolibro", kie vizitantoj lasas enskribojn sub siaj nomoj. La gastlibroj konservas enskribojn forlasitajn pli frue. Estas ankaŭ vizitanto nombrilo ĉe la malsupro de la paĝo.

Linukso-reta aplikaĵo-efikeco. Enkonduko
Reta aplikaĵo "Gastolibro" ZeroHTTPd

La enskriboj de vizitlibroj kaj gastolibroj estas konservitaj en Redis. Por komunikadoj kun Redis, propraj proceduroj estas efektivigitaj; ili ne dependas de la ekstera biblioteko. Mi ne estas granda ŝatanto pri lanĉi hejman kodon kiam ekzistas publike disponeblaj kaj bone testitaj solvoj. Sed la celo de ZeroHTTPd estas studi Linuksan agadon kaj aliron al eksteraj servoj, dum servi HTTP-petojn havas gravan efikecon. Ni devas plene kontroli komunikadojn kun Redis en ĉiu el niaj servilaj arkitekturoj. En iuj arkitekturoj ni uzas blokantajn vokojn, en aliaj ni uzas okazaĵ-bazitajn procedurojn. Uzado de ekstera klienta biblioteko de Redis ne provizos ĉi tiun kontrolon. Aldone, nia malgranda Redis-kliento nur plenumas kelkajn funkciojn (akiri, agordi kaj pligrandigi ŝlosilon; akiri kaj aldoni al tabelo). Krome, la protokolo Redis estas ege eleganta kaj simpla. Vi eĉ ne bezonas speciale instrui ĝin. La fakto mem, ke la protokolo faras la tutan laboron en ĉirkaŭ cent linioj de kodo montras kiom bone pripensita ĝi estas.

La sekva figuro montras kion la aplikaĵo faras kiam la kliento (retumilo) petas /guestbookURL.

Linukso-reta aplikaĵo-efikeco. Enkonduko
Kiel funkcias la gastlibro-aplikaĵo

Kiam gastlibropaĝo devas esti elsendita, estas unu alvoko al la dosiersistemo por legi la ŝablonon en memoron kaj tri retvokoj al Redis. La ŝablona dosiero enhavas la plej grandan parton de la HTML-enhavo por la paĝo en la supra ekrankopio. Estas ankaŭ specialaj anstataŭiloj por la dinamika parto de la enhavo: afiŝoj kaj vizitanto nombrilo. Ni ricevas ilin de Redis, enigas ilin en la paĝon kaj provizas la klienton kun plene formita enhavo. La tria voko al Redis povas esti evitita ĉar Redis resendas la novan ŝlosilvaloron kiam pliigita. Tamen, por nia servilo, kiu havas nesinkronan okazaĵ-bazitan arkitekturon, multaj retaj vokoj estas bona testo por lernado. Do ni forĵetas la revenan valoron de Redis de la nombro da vizitantoj kaj pridemandas ĝin per aparta voko.

Servilaj arkitekturoj ZeroHTTPd

Ni konstruas sep versiojn de ZeroHTTPd kun la sama funkcieco sed malsamaj arkitekturoj:

  • Ripetema
  • Fork-servilo (unu infanprocezo per peto)
  • Antaŭforkservilo (antaŭforkiĝo de procezoj)
  • Servilo kun ekzekutfadenoj (unu fadeno per peto)
  • Servilo kun antaŭfadena kreado
  • Bazita sur arkitekturo poll()
  • Bazita sur arkitekturo epoll

Ni mezuras la rendimenton de ĉiu arkitekturo ŝarĝante la servilon per HTTP-petoj. Sed kiam oni komparas tre paralelajn arkitekturojn, la nombro da demandoj pliiĝas. Ni testas tri fojojn kaj kalkulas la mezumon.

Testa metodiko

Linukso-reta aplikaĵo-efikeco. Enkonduko
ZeroHTTPd-ŝarĝa testado aranĝo

Gravas, ke dum provoj, ĉiuj komponantoj ne funkcias per la sama maŝino. En ĉi tiu kazo, la OS altiras aldonan planadon superkoste ĉar komponentoj konkuras por CPU. Mezuri la operaciumon superkoste de ĉiu el la elektitaj servilaj arkitekturoj estas unu el la plej gravaj celoj de ĉi tiu ekzerco. Aldoni pli da variabloj fariĝos damaĝa al la procezo. Tial, la agordo en la supra bildo funkcias plej bone.

Kion faras ĉiu el ĉi tiuj serviloj?

  • load.unixism.net: Ĉi tie ni kuras ab, Apache Benchmark ilo. Ĝi generas la ŝarĝon necesan por testi niajn servilaj arkitekturoj.
  • nginx.unixism.net: Kelkfoje ni volas ruli pli ol unu ekzemplon de servila programo. Por fari tion, la Nginx-servilo kun la taŭgaj agordoj funkcias kiel ŝarĝbalancilo venanta ab al niaj servilaj procezoj.
  • zerohttpd.unixism.net: Ĉi tie ni rulas niajn servilprogramojn sur sep malsamaj arkitekturoj, unuope.
  • redis.unixism.net: Ĉi tiu servilo kuras la Redis-demonon, kie estas stokitaj gastlibroj kaj vizit-nombriloj.

Ĉiuj serviloj funkcias per la sama procesoro-kerno. La ideo estas taksi la maksimuman rendimenton de ĉiu arkitekturo. Ĉar ĉiuj servilaj programoj estas testitaj sur la sama aparataro, ĉi tio estas bazlinio por komparo. Mia testa aranĝo konsistas el virtualaj serviloj luitaj de Digital Ocean.

Kion ni mezuras?

Vi povas mezuri malsamajn indikilojn. Ni taksas la agadon de ĉiu arkitekturo en difinita agordo ŝarĝante la servilojn per petoj je malsamaj niveloj de paraleleco: la ŝarĝo kreskas de 20 ĝis 15 samtempaj uzantoj.

Testrezultoj

La sekva diagramo montras la agadon de serviloj sur malsamaj arkitekturoj je malsamaj niveloj de paraleleco. La y-akso estas la nombro da petoj je sekundo, la x-akso estas paralelaj ligoj.

Linukso-reta aplikaĵo-efikeco. Enkonduko

Linukso-reta aplikaĵo-efikeco. Enkonduko

Linukso-reta aplikaĵo-efikeco. Enkonduko

Malsupre estas tabelo kun la rezultoj.

petoj por sekundo

paraleleco
ripeta
forko
antaŭforko
streaming
antaŭfluo
enketo
epollo

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
granda disvastiĝo
2138

5000
-
granda disvastiĝo
1600
1100
2519
-
2235

8000
-
-
1200
granda disvastiĝo
2451
-
2100

10
-
-
granda disvastiĝo
-
2200
-
2200

11
-
-
-
-
2200
-
2122

12
-
-
-
-
970
-
1958

13
-
-
-
-
730
-
1897

14
-
-
-
-
590
-
1466

15
-
-
-
-
532
-
1281

El la grafikaĵo kaj tabelo videblas, ke super 8000 samtempaj petoj restas al ni nur du ludantoj: antaŭforko kaj epoll. Ĉar la ŝarĝo pliiĝas, enket-bazita servilo funkcias pli malbone ol fluanta. La faden-antaŭ-krea arkitekturo estas inda konkuranto por epoll, atesto pri kiom bone la Linukso-kerno planas grandajn nombrojn da fadenoj.

Fontkodo ZeroHTTPd

Fontkodo ZeroHTTPd tie. Estas aparta dosierujo por ĉiu arkitekturo.

ZeroHTTPd │ ├── 01_iterativo │ ├── ĉef.c ├── 02_forkaĵo │ ├── ĉef.c ├── 03_preforking │────────── 04_ fadenigado │ ├── ĉefa.c ├── 05_prethreading │ ├── main.c ├── 06_poll │ ├── main.c ├── 07_epoll │ └── publikiga dosiero ── ├─── ├── indekso .html │ └── tux png └── ŝablonoj └── gastlibro └── indekso.html

Krom sep dosierujoj por ĉiuj arkitekturoj, estas du pliaj en la plej alta dosierujo: publika kaj ŝablonoj. La unua enhavas la dosieron index.html kaj la bildon de la unua ekrankopio. Vi povas meti aliajn dosierojn kaj dosierujojn tie, kaj ZeroHTTPd devus servi tiujn senmovajn dosierojn sen problemoj. Se la vojo en la retumilo kongruas kun la vojo en la publika dosierujo, tiam ZeroHTTPd serĉas la index.html dosieron en ĉi tiu dosierujo. La enhavo por la gastlibro estas generita dinamike. Ĝi nur havas ĉefpaĝon, kaj ĝia enhavo baziĝas sur la dosiero 'templates/guestbook/index.html'. ZeroHTTPd facile aldonas dinamikajn paĝojn por etendo. La ideo estas, ke uzantoj povas aldoni ŝablonojn al ĉi tiu dosierujo kaj etendi ZeroHTTPd laŭbezone.

Por konstrui ĉiujn sep servilojn, rulu make all de la plej alta dosierujo - kaj ĉiuj konstruaĵoj aperos en ĉi tiu dosierujo. Efektiveblaj dosieroj serĉas la publikajn kaj ŝablonojn dosierujojn en la dosierujo el kiu ili estas lanĉitaj.

Linukso API

Vi ne bezonas bone koni la Linuksan API por kompreni la informojn en ĉi tiu artikola serio. Tamen mi rekomendas legi pli pri ĉi tiu temo; ekzistas multaj referencresursoj en la Interreto. Kvankam ni tuŝos plurajn kategoriojn de Linukso-API-oj, nia fokuso estos ĉefe pri procezoj, fadenoj, eventoj kaj la reto-stako. Krom libroj kaj artikoloj pri la Linukso API, mi ankaŭ rekomendas legi manaon por sistemvokoj kaj bibliotekfunkcioj uzataj.

Efikeco kaj Skalebleco

Unu noto pri rendimento kaj skaleblo. Teorie, ne ekzistas rilato inter ili. Vi povas havi retservon, kiu funkcias tre bone, kun responda tempo de kelkaj milisekundoj, sed ĝi tute ne skalas. Same, povas ekzisti malbone funkcianta TTT-apliko, kiu bezonas kelkajn sekundojn por respondi, sed ĝi grimpas je dekoj por trakti dekojn da miloj da samtempaj uzantoj. Tamen, la kombinaĵo de alta rendimento kaj skaleblo estas tre potenca kombinaĵo. Alt-efikecaj aplikoj ĝenerale uzas resursojn ŝpareme kaj tiel efike servas pli da samtempaj uzantoj sur la servilo, reduktante kostojn.

CPU kaj I/O-taskoj

Fine, en komputado estas ĉiam du eblaj specoj de taskoj: por I/O kaj CPU. Ricevi petojn tra la Interreto (reto I/O), servado de dosieroj (reto kaj disko I/O), komuniki kun la datumbazo (reto kaj disko I/O) estas ĉiuj I/O-agadoj. Iuj datumbazdemandoj povas esti iom CPU-intensaj (ordigado, averaĝe miliono da rezultoj, ktp.). La plej multaj TTT-aplikoj estas limigitaj per la maksimuma ebla I/O, kaj la procesoro malofte estas uzita ĉe plena kapacito. Kiam vi vidas, ke iu I/O-tasko uzas multe da CPU, ĝi plej verŝajne estas signo de malbona aplika arkitekturo. Ĉi tio povas signifi, ke CPU-resursoj estas malŝparitaj en proceza administrado kaj kuntekstŝanĝo - kaj tio ne estas tute utila. Se vi faras ion kiel pritraktadon de bildoj, konvertiĝon de sondosieroj aŭ maŝinlernadon, tiam la aplikaĵo postulas potencajn CPU-resursojn. Sed por plej multaj aplikoj ĉi tio ne estas la kazo.

Lernu pli pri servilaj arkitekturoj

  1. Parto I: Ripetema Arkitekturo
  2. Parto II. Fork-serviloj
  3. Parto III. Antaŭforkaj serviloj
  4. Parto IV. Serviloj kun fadenoj de ekzekuto
  5. Parto V. Antaŭfadenaj serviloj
  6. Parto VI. Pol-bazita arkitekturo
  7. Parto VII. epoll-bazita arkitekturo

fonto: www.habr.com

Aldoni komenton