SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Jõudluse analüüs ja seadistamine — tugev tööriist jõudlusnõuete vastavuse kontrollimiseks klientidele.

Jõudluse analüüsi saab kasutada programmide kitsaskohtade kontrollimiseks, rakendades teaduslikku lähenemist seadistuste eksperimentide testimisel. See artikkel määratleb üldise lähenemise jõudluse analüüsile ja seadistusele, kasutades näitena Go veebiserverit.

Go sobib siinkohal eriti hästi, kuna sellel on profiilingu tööriistad pprof standardses teegis.

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Strateegia

Loome meie struktuuri analüüsi jaoks kokkuvõtliku nimekirja. Püüame kasutada andmeid otsuste tegemiseks, mitte teha muudatusi, mis põhinevad intuitsioonil või arvamisel. Sellega seoses teeme järgmist:

  • Määrame optimeerimise piirid (nõuded);
  • Arvutame süsteemi tehingukoormuse;
  • Teeme testi (loome andmed);
  • Jälgime;
  • Analüüsime — kas kõik nõuded on täidetud?
  • Seadistame teaduslikult, teeme hüpoteesi;
  • Teeme eksperimenti selle hüpoteesi kontrollimiseks.

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Lihtsa HTTP serveri arhitektuur

Selles artiklis kasutame väikest HTTP-serverit Golangi peal. Kogu selle artikli kood on saadaval. siit.

Analüüsitav rakendus on HTTP-server, mis küsib iga küsimuse puhul Postgresql'lt. Samuti on olemas Prometheus, node_exporter ja Grafana, et koguda ja kuvada rakenduse ja süsteemi mõõdikuid.

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Lihtsustamiseks oletame, et iga teenus ja andmebaas paigaldatakse koos horisontaalse skaleerimise (ja arvutuste lihtsustamise) jaoks:

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Määratleme eesmärgid

Selles etapis määratleme eesmärgi. Mida me püüame analüüsida? Kuidas me saame teada, millal lõpetada? Sellest artiklist lähtuvalt oletame, et meil on kliendid ja et meie teenus hakkab töötlema 10 000 päringut sekundis.

V Google SRE Raamat käsitletakse üksikasjalikult valikute ja modelleerimise viise. Teeme samuti, ehitame mudelid:

  • Viivitus: 99% päringutest peaks toimuma vähem kui 60 ms;
  • Hind: teenus peaks tarbima minimaalset summat raha, mida peame mõistlikuks. Selleks maksimeerime läbilaskevõime.
  • Mahutite planeerimine: vajalik on mõista ja dokumenteerida, kui palju rakenduse koopiaid on vaja käivitada, sealhulgas üldine skaleerimise funktsioon, samuti kui palju koopiaid on vajalik algsete koormuse nõuete rahuldamiseks ja tagamise. ülemäärasus n+1.

Latentsus võib vajada optimeerimist koos analüüsiga, kuid läbilaskevõime tuleb selgelt analüüsida. SRE protsessi SLO kasutamisel tuleneb latentsuse nõue kliendilt või ettevõttelt, mille esindab toote omanik. Meie teenus täidab selle kohustuse algusest peale ilma igasuguste seadistusteta!

Konfigureeritav testkeskkond

Testkeskkonna abil suudame meie süsteemile doseeritud koormust anda. Analüüsi jaoks luuakse veebiteenuse jõudluse andmed.

Tehingukoormus

See keskkond kasutab Vegeta kohandatud HTTP päringute sageduse genereerimiseks, kuni see peatatakse:

$ make load-test LOAD_TEST_RATE=50
echo "POST http://localhost:8080" | vegeta attack -body tests/fixtures/age_no_match.json -rate=50 -duration=0 | tee results.bin | vegeta report

Jälgimine

Teostamise käigus rakendatakse tehingukoormust. Lisaks rakenduse mõõdikutele (päringute arv, vastuse viivitus) ja operatsioonisüsteemi (mälumahu, CPU, IOPS) käivitatakse rakenduse profiilimine, et mõista, kus selles on probleeme, ning kuidas protsessorite mõiste kasutamine toimub.

Profiilimine

Profiilimine on mõõtmise tüüp, mis võimaldab näha, kuhu suunatakse protsessorite aeg rakenduse töö käigus. See aitab määrata, kus ja kui palju protsessorite aega kulutatakse:

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Neid andmeid saab kasutada analüüsi käigus, et saada ülevaade mõttetult kulutatud protsessorite ajast ja teostatud tarbetust tööst. Go (pprof) suudab genereerida profiile ja visualiseerida neid leekgraafikuna, kasutades standardset tööriistade komplekti. Räägin nende kasutamisest ja seadistamisjuhendist allpool artiklis.

Teostamine, jälgimine, analüüs.

Teeme eksperimenti. Me jälgime ja analüüsime, kuni jõuame saavutada soovitud jõudluse. Valime suvaliselt madala koormuse, et rakendada seda esimeste tähelepanekute saamiseks. Igal järgmisel sammul suurendame koormust mingi skaleerimisteguriga, mis on valitud teatud vahemikus. Iga koormustesti käivitatakse, reguleerides päringute arvu: make load-test LOAD_TEST_RATE=X.

50 päringut sekundis

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Pange tähele kahte ülemist graafikut. Ülemine vasak näitab, et meie rakendus töötleb 50 päringut sekundis (tema arvates), ja ülemine parem graafik näitab iga päringu kestust. Mõlemad parameetrid aitavad meil vaatleda ja analüüsida: kas jääme oma jõudluspiiridesse või mitte. Grafiku punane joon HTTP Päringu Latentsus näitab SLO-d 60 ms. Joone järgi on näha, et oleme oma maksimaalsest vastuse ajast kaugel allpool.

Vaadakem kulupoolt:

10000 päringut sekundis / 50 päringut serveri kohta = 200 serverit + 1

Saame seda näitajat ikka veel parandada.

500 päringut sekundis

Huvitavamad asjad hakkavad juhtuma, kui koormus ulatub 500 päringuni sekundis:

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Nagu vasakul ülemisel graafikul näha, registreerib rakendus tavalise koormuse. Kui see nii ei ole, on serveris, kus rakendus töötab, probleem. Ülemisel paremal graafikul, mis näitab vastuse viivitust, on näha, et 500 päringut sekundis viis vastuse viivituse 25–40 ms. 99. protsentiil mahtus endiselt suurepäraselt valitud SLO-sse 60 ms.

Kulude seisukohalt:

10000 päringut sekundis / 500 päringut serveri kohta = 20 serverit + 1

Seda saab endiselt parandada.

1000 päringut sekundis

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Suurepärane käivitus! Rakendus näitab, et see töötles 1000 päringut sekundis, kuid viivituse piirang SLO-s ületati. Seda on näha p99 joone pealt ülemisel paremal graafikul. Kuigi p100 joon on palju kõrgem, on reaalsed viivitused üle maksimaalse 60 ms. Sukeldugem profiilimiseks, et teada saada, mida rakendus tegelikult teeb.

Profiilimine

Profiilimiseks paneme koormuse 1000 päringuni sekundis, seejärel kasutame pprof andmete kogumiseks, et mõista, kus rakendus protsessoriaega kulutab. Seda saab teha, aktiveerides HTTP lõpp-punkti pprof, pärast mida koormuse all salvestame tulemused kasutades curl:

$ curl http://localhost:8080/debug/pprof/profile?seconds=29 > cpu.1000_reqs_sec_no_optimizations.prof

Tulemusi saab kuvada järgmiselt:

$ go tool pprof -http=:12345 cpu.1000_reqs_sec_no_optimizations.prof

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Graafik näitab, kus ja kui palju rakendus protsessoriaega kulutab. Kirjelduse kohaselt Brendan Gregg:

X-telg – virna täitmine, sorteeritud tähestikulises järjekorras (see ei ole aeg), Y-telg näitab virna sügavust, alates nullist [top]-ist. Iga ristkülik on virna kaader. Mida laiem kaader, seda sagedamini see virnades esineb. Ülalpool – töötab CPU-l, allpool – alamsüsteemid. Värvid ei tähenda tavaliselt midagi, vaid valitakse lihtsalt juhuslikult, et eristada kaadreid.

Analüüs – hüpotees

Seadistamiseks keskendume katsetele leida tarbetud protsessoriaja kulutusi. Otsime suurimaid tarbetute kulutuste allikaid ja eemaldame need. Kuna profiilimine näitab väga täpselt, kus rakendus oma protsessoriaega kulutab, võib osutuda vajalikuks seda mitu korda korrata ning samuti tuleb muuta rakenduse lähtekoodi, taaskäivitada testid ja jälgida, et jõudlus oleks kavandatule lähedal.

Järgime Brendan Greggi soovitusi ja vaatame graafikut ülevalt alla. Iga rida esindab virnastamisraami (funktsiooni üleskutset). Esimene rida on programmi sisendpunkt, teiste kutsungite vanem (teiste sõnadega, kõik teised kutsungid on tema virnas). Järgmine rida on juba erinev:

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Kui viidate funktsiooni nimele graafikul, kuvatakse koguaeg, kui kaua ta virnas oli silumi ajal. Funktsioon HTTPServe oli seal 65% ajast, teised runtime-funktsioonid, runtime.mcall, mstart ja gc, võtsid ülejäänud aja. Huvi asjaolu: 5% koguajast kulus DNS-päringutele:

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Aadressid, mida programm otsib, kuuluvad Postgresql'ile. Klikkame FindByAge:

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Huvitav on see, et programm näitab, et põhimõtteliselt on kolm peamist allikat, mis lisavad viivitusi: ühenduste avamine ja sulgemine, andmete päring ning andmebaasi sisselogimine. Graafikult on näha, et DNS-i päringud, ühenduste avamine ja sulgemine võtavad ligikaudu 13% kogu töötlusajast.

Hüpotees: Ühenduste taaskasutamine ühenduste puu kaudu peaks vähendama ühe HTTP päringu aega, võimaldades kõrgemat läbilaskevõimet ja madalamaid viivitusi..

Rakenduse seadistamine — eksperiment.

Värskendame lähtekoodi, proovime eemaldada Postgresql-iga ühenduse iga päringu korral. Esimene variant — kasutamine. ühenduste puu. Selles eksperimendis me seame ühenduste puu sql draiveri abil go jaoks:

db, err := sql.Open("postgres", dbConnectionString)
db.SetMaxOpenConns(8)

if err != nil {
   return nil, err
}

Täideviimine, jälgimine, analüüs.

Pärast 1000 päringu sekundis testi taaskäivitamist on näha, et p99 viivitused on normi lähedale jõudnud, SLO 60ms!

Kuidas on kulud?

10000 päringut sekundis / 1000 päringut serverisse = 10 serverit + 1.

Teeme veelgi paremini!

2000 päringut sekundis.

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Koormuse kahekordistamine näitab sama: vasaku ülanurga graafik illustreerib, et rakendus suudab töötada välja 2000 päringut sekundis, p100 alla 60 ms, p99 vastab SLO-le.

Kulude seisukohalt:

10000 päringut sekundis / 2000 päringut serveri kohta = 5 serverit + 1

3000 päringut sekundis

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Siin suudab rakendus töödelda 3000 päringut, p99 viivitusega alla 60 ms. SLO-d ei rikutud ja kulus on arvutatud järgmiselt:

10000 päringut sekundis / 3000 päringut serveri kohta = 4 serverit + 1 (autor ümardas suuremaks, tõlkija märk.)

Proovime veel ühte analüüsi vooru.

Analüüs – hüpotees

Kogume ja kuvame tulemusi rakenduse tõrkeotsingust 3000 päringuga sekundis:

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Endiselt 6% ajast kulub ühenduste loomisele. Loodud bassein parandas jõudlust, kuid on näha, et rakendus jätkab uute ühenduste loomist andmebaasiga.

Hüpotees: Ühendused, hoolimata basseinist, eemaldatakse ja puhastatakse endiselt, seetõttu peab rakendus need uuesti looma. Ootavate ühenduste arvu seadmine basseini suurusele peaks aitama viivitust vähendada, minimeerides aja, mida rakendus kulutab ühenduse loomisele..

Rakenduse seadistamine — eksperiment.

Proovime seada MaxIdleConns samade suurusele basseinile (kirjeldatakse ka siit):

db, err := sql.Open("postgres", dbConnectionString)
db.SetMaxOpenConns(8)
db.SetMaxIdleConns(8)
if err != nil {
   return nil, err
}

Täideviimine, jälgimine, analüüs.

3000 päringut sekundis

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

p99 alla 60ms koos oluliselt madalama p100-ga!

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Flame graafi kontroll näitab, et ühenduse seadmine pole enam nähtav! Kontrollime lähemalt pg(*conn).query — ka siin ei märka ühenduse seadmist.

SRE: Jõudluse analüüs. Kuidas seadistada lihtsa Go veebiserveriga

Kokkuvõte

Mugavuse analüüs on kriitilise tähtsusega, et mõista, kas kliendi ootused ja mittefunktsionaalsed nõuded on täidetud. Analüüs, võrreldes tähelepanekuid klientide ootustega, võib aidata kindlaks teha, mis on vastuvõetav ja mis mitte. Go pakub tõhusaid tööriistu, mis on integreeritud standardteeki, et muuta analüüs lihtsaks ja kergesti ligipääsetavaks.

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster