Ytelsen til nettapplikasjoner i Linux. Introduksjon

Webapplikasjoner brukes nÄ overalt, og blant alle transportprotokoller utgjÞr HTTP en stor del. NÄr man utforsker detaljene ved utvikling av webapplikasjoner, legger de fleste svÊrt lite vekt pÄ operativsystemet der disse applikasjonene faktisk kjÞrer. Delingen av utvikling (Dev) og drift (Ops) har bare forverret situasjonen. Men med spredningen av DevOps-kulturen begynner utviklerne Ä ta ansvar for Ä kjÞre sine applikasjoner i skyen, sÄ det er svÊrt nyttig for dem Ä bli godt kjent med backend-operativsystemet. Dette er spesielt nyttig hvis du prÞver Ä distribuere et system for tusenvis eller titusenvis av samtidige tilkoblinger.

Begrensninger i webtjenester ligner veldig pĂ„ begrensninger i andre applikasjoner. Enten det er lastbalanserere eller databaser, har alle disse applikasjonene lignende utfordringer i hĂžyytelsesmiljĂžet. Å forstĂ„ disse grunnleggende begrensningene og mĂ„tene Ă„ omgĂ„ dem pĂ„, vil generelt gjĂžre det lettere Ă„ evaluere ytelsen og skalerbarheten til webapplikasjonene dine.

Jeg skriver denne serien med artikler som svar pÄ spÞrsmÄl fra unge utviklere som Þnsker Ä bli godt informerte systemarkitekter. Det er umulig Ä forstÄ metodene for optimalisering av Linux-applikasjoner klart uten Ä dykke ned i grunnleggende prinsipper for hvordan de fungerer pÄ operativsystemnivÄ. Selv om det finnes mange typer applikasjoner, Þnsker jeg Ä utforske nettverksapplikasjoner i denne syklusen, ikke skrivebordsapplikasjoner som nettlesere eller tekstredigerere. Dette materialet er rettet mot utviklere og arkitekter som Þnsker Ä forstÄ hvordan programmer pÄ Linux eller Unix fungerer og hvordan de kan struktureres for hÞy ytelse.

Linux er et server operativsystem, og oftest kjÞrer applikasjonene dine pÄ dette OS-et. Selv om jeg sier «Linux», kan du stort sett med trygghet anta at jeg refererer til alle Unix-lignende operativsystemer generelt. Likevel har jeg ikke testet den medfÞlgende koden pÄ andre systemer. SÄ hvis du er interessert i FreeBSD eller OpenBSD, kan resultatet variere. NÄr jeg prÞver noe spesifikt for Linux, vil jeg pÄpeke dette.

Selv om du kan bruke den tilegnede kunnskapen til Ä lage en applikasjon fra bunnen av, og den vil vÊre strÄlende optimalisert, er det best Ä ikke gjÞre det. Hvis du skriver en ny webserver i C eller C++ for forretningsapplikasjonen til organisasjonen din, kan det vÊre din siste dag pÄ jobben. Men kunnskap om strukturen til disse applikasjonene vil hjelpe deg Ä velge eksisterende programmer. Du vil kunne sammenligne systemer basert pÄ prosesser med systemer basert pÄ trÄder, samt basert pÄ hendelser. Du vil forstÄ og vurdere hvorfor Nginx fungerer bedre enn Apache httpd, samt hvorfor en Python-applikasjon basert pÄ Tornado kan betjene flere brukere sammenlignet med en Python-applikasjon basert pÄ Django.

ZeroHTTPd: lĂŠringsverktĂžy

ZeroHTTPd — en webserver som jeg skrev fra bunnen av i C som et lĂŠringsverktĂžy. Den har ingen eksterne avhengigheter, inkludert tilgang til Redis. Vi kjĂžrer vĂ„re egne Redis-prosedyrer. Se mer nedenfor.

Selv om vi kunne diskutere teorien i lang tid, er det ingenting bedre enn Ä skrive kode, kjÞre den og sammenligne de ulike serverarkitekturene. Dette er den mest illustrative metoden. Derfor skal vi skrive en enkel webserver, ZeroHTTPd, og bruke hver modell: basert pÄ prosesser, trÄder og hendelser. Vi vil teste hver av disse serverne og se hvordan de fungerer sammenlignet med hverandre. ZeroHTTPd implementeres i én C-fil. Serveren basert pÄ hendelser inkluderer uthash, en utmerket implementering av en hashtabell som leveres i én header-fil. Ellers er det ingen avhengigheter for Ä unngÄ Ä komplisere prosjektet.

Koden har mange kommentarer for Ä hjelpe med forstÄelsen. Som en enkel webserver med noen fÄ linjer kode fungerer ZeroHTTPd ogsÄ som et minimalt rammeverk for webutvikling. Den har begrenset funksjonalitet, men kan levere statiske filer og veldig enkle «dynamiske» sider. Jeg mÄ si at ZeroHTTPd er godt egnet for Ä lÊre hvordan man lager hÞyytelses Linux-applikasjoner. I bunn og grunn venter de fleste webtjenester pÄ forespÞrslene, sjekker dem og behandler dem. Det er nettopp det ZeroHTTPd vil gjÞre. Det er et lÊringsverktÞy, ikke for produksjon. Den er ikke sterk pÄ feilhÄndtering og kan knapt skryte av beste sikkerhetspraksis (Ä ja, jeg brukte strcpy) eller med smÄsprÄkelige triks av C-sprÄket. Men jeg hÄper det vil gjÞre oppgaven sin godt.

Ytelsen til nettapplikasjoner i Linux. Introduksjon
Forside for ZeroHTTPd. Den kan levere forskjellige filtyper, inkludert bilder.

Gjestebok-applikasjonen

Moderne webapplikasjoner er vanligvis ikke begrenset til statiske filer. De har kompliserte interaksjoner med forskjellige databaser, cacher, etc. Derfor vil vi lage en enkel webapplikasjon kalt «Gjestebok», hvor besÞkende kan legge igjen meldinger med navnet sitt. I gjesteboken lagres tidligere meldinger. Det finnes ogsÄ en besÞksteller nederst pÄ siden.

Ytelsen til nettapplikasjoner i Linux. Introduksjon
Webapplikasjonen «Gjestebok» ZeroHTTPd

BesÞkstelleren og meldinger fra gjesteboken lagres i Redis. For kommunikasjon med Redis er det implementert egne prosedyrer som ikke er avhengige av eksterne biblioteker. Jeg er ikke en stor fan av Ä utvikle egen kode nÄr det finnes offentlige og godt testede lÞsninger. Men mÄlet med ZeroHTTPd er Ä utforske ytelsen til Linux og tilgangen til eksterne tjenester, mens hÄndtering av HTTP-forespÞrselene alvorlig pÄvirker ytelsen. Vi mÄ ha full kontroll over kommunikasjonen med Redis i hver av vÄre serverarkitekturer. I en arkitektur bruker vi blokkerende kall, i andre - hendelsesbaserte prosedyrer. Bruken av et eksternt klientbibliotek for Redis vil ikke gi en slik kontroll. I tillegg utfÞrer vÄr lille Redis-klient bare et par funksjoner (hente, sette og inkrementere en nÞkkel; hente og legge til i en array). Dessuten er protokollen til Redis eksepsjonelt elegant og enkel. Den trenger ikke spesiell opplÊring. Det faktum at hele arbeidet protokollen gjÞr, kan utfÞres pÄ omtrent hundre linjer med kode, sier noe om hvor godt det er gjennomtenkt.

I det fÞlgende bildet vises aktiviteter i applikasjonen nÄr klienten (nettleseren) sender en forespÞrsel. /guestbookURL.

Ytelsen til nettapplikasjoner i Linux. Introduksjon
Mekanismen for drift av gjestebok-applikasjonen

NÄr en side for gjesteboken skal genereres, skjer det ett kall til filsystemet for Ä lese malen inn i minnet, og tre nettverkskall til Redis. Malfilen inneholder mesteparten av HTML-innholdet for siden pÄ skjermbildet over. Det finnes ogsÄ spesielle plassholdere for den dynamiske delen av innholdet: innlegg og besÞkstelleren. Vi henter dem fra Redis, setter dem inn pÄ siden og leverer kunden det fullstendig formede innholdet. Det tredje kallet til Redis kan unngÄs, siden Redis returnerer en ny verdi for nÞkkelen nÄr den Þkes. Imidlertid, for vÄr server med en asynkron arkitektur basert pÄ hendelser, er mange nettverkskall en god trening i lÊringsÞyemed. Dermed slipper vi den returnerte verdien fra Redis om antall besÞkende og ber om den med et eget kall.

Serverarkitekturer ZeroHTTPd

Vi bygger syv versjoner av ZeroHTTPd med identisk funksjonalitet, men forskjellige arkitekturer:

  • Iterativ
  • Fork-server (ett dataprogramprosess per forespĂžrsel)
  • Pre-fork server (forhĂ„ndsforgrening av prosesser)
  • Server med trĂ„der (en trĂ„d per forespĂžrsel)
  • Server med forhĂ„ndsskaping av trĂ„der
  • Arkitektur basert pĂ„ poll()
  • Arkitektur basert pĂ„ epoll

Vi mÄler ytelsen til hver arkitektur ved Ä belaste serveren med HTTP-forespÞrsel. Men nÄr man sammenligner arkitekturer med hÞy grad av parallellisme, Þker antallet forespÞrsel. Vi tester tre ganger og regner ut gjennomsnittet.

Testmetodologi

Ytelsen til nettapplikasjoner i Linux. Introduksjon
Oppsett for belastningstest av ZeroHTTPd

Det er viktig at ikke alle komponenter kjĂžrer pĂ„ Ă©n maskin nĂ„r testene utfĂžres. I sĂ„ fall pĂ„fĂžrer operativsystemet ekstra kostnader for planlegging, ettersom komponentene konkurrerer om CPU-en. Å mĂ„le operativsystemets overhead med hver av de valgte serverarkitekturene er et av de viktigste mĂ„lene med dette Ăžvelsen. Å legge til flere variabler vil vĂŠre skadelig for prosessen. Derfor fungerer oppsettet pĂ„ bildet over best.

Hva gjĂžr hver av disse serverne

  • load.unixism.net: her kjĂžrer vi ab, Apache Benchmark-verktĂžyet. Det genererer belastningen som kreves for Ă„ teste vĂ„re serverarkitekturer.
  • nginx.unixism.net: noen ganger Ăžnsker vi Ă„ kjĂžre mer enn Ă©n instans av serverprogrammet. For dette fungerer Nginx-serveren med de riktige innstillingene som en belastningsfordeler som mottar ab til vĂ„re serverprosesser.
  • zerohttpd.unixism.net: her kjĂžrer vi programmene vĂ„re pĂ„ syv ulike arkitekturer, Ă©n av gangen.
  • redis.unixism.net: pĂ„ denne serveren kjĂžrer Redis-daemonen, der oppfĂžringene i gjesteboken og besĂžksstatistikken lagres.

Alle servere kjÞrer pÄ ett prosessorkjerne. Ideen er Ä vurdere den maksimale ytelsen til hver arkitektur. Siden alle serverprogrammer blir testet pÄ det samme utstyret, er dette et basisnivÄ for sammenligning. Min testoppsett bestÄr av virtuelle servere leid fra Digital Ocean.

Hva mÄler vi?

Vi kan mÄle ulike indikatorer. Vi evaluerer ytelsen til hver arkitektur i denne konfigurasjonen, ved Ä laste serverne med forespÞrselene pÄ forskjellige nivÄer av parallellisme: belastningen Þker fra 20 til 15 000 samtidige brukere.

Testresultater

I diagrammet nedenfor vises ytelsen til serverne pÄ forskjellige arkitekturer ved forskjellige nivÄer av parallellisme. PÄ y-aksen er antall forespÞrseler per sekund, pÄ x-aksen er parallelle tilkoblinger.

Ytelsen til nettapplikasjoner i Linux. Introduksjon

Ytelsen til nettapplikasjoner i Linux. Introduksjon

Ytelsen til nettapplikasjoner i Linux. Introduksjon

Under er tabellen med resultatene.

forespĂžrseler per sekund

parallellisme
iterativ
fork
pre-fork
trÄd-basert
pre-trÄd-basert
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
stor spredning
2138

5000
–
stor spredning
1600
1100
2519
–
2235

8000
–
–
1200
stor spredning
2451
–
2100

10 000
–
–
stor spredning
–
2200
–
2200

11 000
–
–
–
–
2200
–
2122

12 000
–
–
–
–
970
–
1958

13 000
–
–
–
–
730
–
1897

14 000
–
–
–
–
590
–
1466

15 000
–
–
–
–
532
–
1281

Fra grafen og tabellen kan vi se at over 8000 samtidige forespÞrseler er det bare to aktÞrer igjen: pre-fork og epoll. Med Þkende belastning fungerer serveren basert pÄ poll dÄrligere enn den trÄd-baserte. Arkitekturen med forhÄndsopprettede trÄder gir en solid konkurranse til epoll: dette vitner om hvor godt Linux-kjernen planlegger et stort antall trÄder.

Kildekode for ZeroHTTPd

Kildekode for ZeroHTTPd her. For hver arkitektur er det en egen katalog.

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

I tillegg til de syv katalogene for alle arkitekturer, finnes det to andre i rotkatalogen: public og templates. I den fÞrste ligger filen index.html og bildet fra det fÞrste skjermbildet. Du kan plassere andre filer og mapper der, og ZeroHTTPd bÞr uten problemer servere disse statiske filene. Hvis stien i nettleseren samsvarer med stien i public-mappen, vil ZeroHTTPd sÞke etter filen index.html i denne katalogen. Innholdet til gjesteboken genereres dynamisk. Det har bare en hovedside, og dens innhold er basert pÄ filen 'templates/guestbook/index.html'. Det er enkelt Ä legge til dynamiske sider i ZeroHTTPd for utvidelse. Ideen er at brukere kan legge til maler i denne katalogen og utvide ZeroHTTPd etter behov.

For Ă„ bygge alle de syv serverne, kjĂžr make all fra rotkatalogen - og alle byggefilene vil dukke opp i denne katalogen. KjĂžrbare filer leter etter katalogene public og templates i den katalogen de kjĂžres fra.

Linux API

For Ä forstÄ informasjonen i denne artikkelserien, trenger du ikke Ä ha en god forstÄelse av Linux API. Jeg anbefaler imidlertid Ä lese mer om emnet; det finnes mange referanser pÄ nettet. Selv om vi vil berÞre flere kategorier av Linux API, vil vÄrt fokus hovedsakelig vÊre pÄ prosesser, trÄder, hendelser og nettverksstabler. I tillegg til bÞker og artikler om Linux API, anbefaler jeg ogsÄ Ä lese man-sider for systemkall og brukte biblioteksfunksjoner.

Ytelse og skalerbarhet

En kommentar om ytelse og skalerbarhet. Teoretisk sett er det ingen sammenheng mellom dem. Du kan ha en webtjeneste som fungerer veldig bra, med responstider pÄ noen millisekunder, men som ikke skaleres i det hele tatt. PÄ samme mÄte kan det vÊre en dÄrlig fungerende webapplikasjon som tar flere sekunder Ä svare, men som skalerer til titalls for Ä hÄndtere titusener av samtidige brukere. Likevel er kombinasjonen av hÞy ytelse og skalerbarhet en veldig kraftig kombinasjon. HÞyytelsesapplikasjoner bruker generelt ressurser Þkonomisk og betjener dermed flere samtidige brukere pÄ serveren, noe som reduserer kostnadene.

CPU- og I/O-oppgaver

Til slutt, i beregningene finnes det alltid to mulige typer oppgaver: for I/O og CPU. HĂ„ndtering av forespĂžrslene via internett (nettverksinngang/utgang), filbearbeiding (nettverks og disk I/O), kommunikasjon med databasen (nettverks og disk I/O) – alt dette er I/O-oppgaver. Enkelte forespĂžrsel til databasen kan belaste CPU en smule (sortering, beregning av gjennomsnittet av millioner av resultater, osv.). De fleste webapplikasjoner er begrenset av det maksimalt mulige I/O, mens prosessoren sjeldent brukes til sin fulle kapasitet. NĂ„r du ser at en eller annen oppgave for inngang/utgang bruker mye CPU, er det mest sannsynlig et tegn pĂ„ dĂ„rlig applikasjonsarkitektur. Dette kan bety at CPU-ressursene brukes til prosesshĂ„ndtering og kontekstbytter - og det er ikke helt nyttig. Hvis du gjĂžr noe som bildebehandling, konvertering av lydfiler eller maskinlĂŠring, vil applikasjonen kreve kraftige CPU-ressurser. Men for de fleste applikasjoner er det ikke tilfelle.

Mer om serverarkitekturer

  1. Del I. Iterativ arkitektur
  2. Del II. Fork-servere
  3. Del III. Pre-fork servere
  4. Del IV. Servere med trÄder
  5. Del V. Servere med forhÄndsskapt trÄder
  6. Del VI. Arkitektur basert pÄ poll
  7. Del VII. Arkitektur basert pÄ epoll

Kilde: habr.com

KjĂžp pĂ„litelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere đŸ”„ KjĂžp pĂ„litelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere | ProHoster