SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Jõudlusanalüüs ja häälestamine on võimas tööriist klientide jõudluse vastavuse kontrollimiseks.

Jõudlusanalüüsi abil saab kontrollida programmi kitsaskohti, rakendades häälestuskatsete testimisel teaduslikku lähenemist. See artikkel määratleb üldise lähenemisviisi jõudluse analüüsile ja häälestamisele, kasutades näiteks Go veebiserverit.

Go on siin eriti hea, kuna sellel on profiilide koostamise tööriistad pprof standardraamatukogus.

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

strateegia

Koostame oma struktuurianalüüsi jaoks kokkuvõtliku loendi. Püüame kasutada mõningaid andmeid otsuste tegemiseks, selle asemel, et intuitsioonil või oletusel põhinevaid muudatusi teha. Selleks teeme järgmist:

  • Määrame optimeerimise piirid (nõuded);
  • Arvutame süsteemi tehingukoormuse;
  • Teostame testi (loome andmed);
  • Me jälgime;
  • Analüüsime – kas kõik nõuded on täidetud?
  • Seadsime selle teaduslikult paika, püstitame hüpoteesi;
  • Teeme selle hüpoteesi kontrollimiseks katse.

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Lihtne HTTP-serveri arhitektuur

Selle artikli jaoks kasutame Golangis väikest HTTP-serverit. Kogu selle artikli koodi leiate siin.

Analüüsitav rakendus on HTTP-server, mis küsitleb iga päringu kohta Postgresql-i. Lisaks on rakenduste ja süsteemi mõõdikute kogumiseks ja kuvamiseks Prometheus, node_exporter ja Grafana.

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Lihtsustamiseks arvestame, et horisontaalseks skaleerimiseks (ja arvutuste lihtsustamiseks) juurutatakse iga teenus ja andmebaas koos:

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Eesmärkide määratlemine

Selles etapis otsustame eesmärgi üle. Mida me püüame analüüsida? Kuidas me teame, millal on aeg lõpetada? Selles artiklis kujutame ette, et meil on kliente ja meie teenus töötleb 10 000 päringut sekundis.

В Google SRE raamat Üksikasjalikult käsitletakse valiku- ja modelleerimismeetodeid. Teeme sama ja ehitame mudeleid:

  • Latentsus: 99% taotlustest peaks olema täidetud vähem kui 60 ms jooksul;
  • Maksumus: teenus peaks kulutama minimaalse summa raha, mis meie arvates on mõistlikult võimalik. Selleks maksimeerime läbilaskevõimet;
  • Võimsuse planeerimine: nõuab arusaamist ja dokumenteerimist, kui palju rakenduse eksemplare peab töötama, sealhulgas üldist skaleerimisfunktsiooni, ja mitut eksemplari on vaja esialgse laadimise ja varustamise nõuete täitmiseks. koondamine n+1.

Latentsusaeg võib vajada lisaks analüüsile optimeerimist, kuid läbilaskevõimet tuleb selgelt analüüsida. SRE SLO protsessi kasutamisel tuleb viivitustaotlus kliendilt või ettevõttelt, keda esindab toote omanik. Ja meie teenus täidab selle kohustuse algusest peale ilma igasuguste seadistusteta!

Testikeskkonna seadistamine

Testkeskkonna abil saame oma süsteemile panna mõõdetud koormuse. Analüüsiks genereeritakse andmed veebiteenuse toimivuse kohta.

Tehingukoormus

See keskkond kasutab kiratsema kohandatud HTTP päringu kiiruse loomiseks kuni peatamiseni:

$ 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

Vaatlus

Tehingukoormus rakendatakse käitusajal. Lisaks rakenduse (päringute arv, vastuse latentsus) ja operatsioonisüsteemi (mälu, protsessor, IOPS) mõõdikutele käivitatakse rakenduse profiilide koostamine, et mõista, kus sellel on probleeme ja kuidas kulub protsessori aega.

Profileerimine

Profileerimine on mõõtmise tüüp, mis võimaldab rakenduse töötamise ajal näha, kuhu protsessori aeg kulub. See võimaldab teil täpselt määrata, kuhu ja kui palju protsessori aega kulutatakse:

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Neid andmeid saab analüüsi ajal kasutada, et saada ülevaade raisatud protsessori ajast ja tehtavast tarbetust tööst. Go (pprof) saab standardsete tööriistade komplekti kasutades luua profiile ja visualiseerida neid leegigraafikutena. Nende kasutamisest ja seadistamise juhendist räägin hiljem artiklis.

Teostus, vaatlus, analüüs.

Teeme katse. Esineme, vaatleme ja analüüsime seni, kuni oleme sooritusega rahul. Esimeste vaatluste tulemuste saamiseks valime selle rakendamiseks suvaliselt väikese koormuse väärtuse. Igal järgneval etapil suurendame koormust teatud skaleerimisteguriga, mis on valitud teatud variatsioonidega. Iga koormustesti käitamine tehakse kohandatud taotluste arvuga: make load-test LOAD_TEST_RATE=X.

50 päringut sekundis

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Pöörake tähelepanu kahele ülemisele graafikule. Vasakpoolses ülanurgas on näha, et meie rakendus töötleb 50 päringut sekundis (ta arvab) ja üleval paremal on iga päringu kestus. Mõlemad parameetrid aitavad meil vaadata ja analüüsida, kas oleme oma tulemuslikkuse piirides või mitte. Punane joon graafikul HTTP päringu latentsus näitab SLO-d 60 ms juures. Joon näitab, et oleme oma maksimaalsest reageerimisajast kõvasti alla jäänud.

Vaatame kulude poolt:

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

Seda näitajat saame veel parandada.

500 päringut sekundis

Huvitavamad asjad hakkavad juhtuma siis, kui koormus jõuab 500 päringuni sekundis:

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Jällegi on üleval vasakpoolsel graafikul näha, et rakendus salvestab tavalist koormust. Kui see nii ei ole, on probleem serveris, kus rakendus töötab. Vastuse latentsusgraafik asub paremas ülanurgas, mis näitab, et 500 päringut sekundis põhjustas vastuse viivituse 25–40 ms. 99. protsentiil sobib ikka kenasti ülal valitud 60ms SLO-sse.

Kulude osas:

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

Kõike saab veel parandada.

1000 päringut sekundis

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Suurepärane käivitamine! Rakendus näitab, et see töötles 1000 päringut sekundis, kuid SLO rikkus latentsuspiirangut. Seda on näha parempoolse graafiku real p99. Vaatamata asjaolule, et p100 liin on palju kõrgem, on tegelikud viivitused suuremad kui maksimaalne 60 ms. Sukeldume profiilide koostamisse, et teada saada, mida rakendus tegelikult teeb.

Profileerimine

Profileerimiseks määrame koormuse 1000 päringut sekundis, seejärel kasuta pprof andmete kogumiseks, et teada saada, kus rakendus CPU aega kulutab. Seda saab teha HTTP lõpp-punkti aktiveerimisega pprofja seejärel salvestage tulemused koormuse all curl abil:

$ 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: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Graafik näitab, kus ja kui palju rakendus CPU aega kulutab. Alates kirjeldusest alates Brendan Gregg:

X-telg on virna profiili populatsioon, sorteeritud tähestikulises järjekorras (see pole aeg), Y-telg näitab virna sügavust, lugedes nullist [üleval]. Iga ristkülik on virnaraam. Mida laiem on raam, seda sagedamini on see virnades. See, mis on peal, töötab CPU-s ja allpool olevad on alamelemendid. Värvid ei tähenda tavaliselt midagi, vaid valitakse lihtsalt juhuslikult, et raame eristada.

Analüüs – hüpotees

Häälestamiseks keskendume raisatud protsessoriaja leidmisele. Otsime üles suurimad asjatute kulutuste allikad ja eemaldame need. Arvestades, et profiilide koostamine näitab väga täpselt, kus rakendus täpselt oma protsessori aega kulutab, peate võib-olla seda mitu korda tegema, samuti peate muutma rakenduse lähtekoodi, uuesti läbima testid ja veenduma, et jõudlus läheneb eesmärgile.

Järgides Brendan Greggi soovitusi, loeme diagrammi ülalt alla. Igal real kuvatakse virnaraam (funktsiooni kutse). Esimene rida on programmi sisenemispunkt, kõigi teiste kõnede vanem (teisisõnu on see kõigi teiste kõnede pinus). Järgmine rida on juba erinev:

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Kui hõljutate kursorit graafikul funktsiooni nime kohal, kuvatakse kogu aeg, mil see silumise ajal virnas oli. Funktsioon HTTPServe oli seal 65% ajast, muud käitusaegsed funktsioonid runtime.mcall, mstart и gc, võttis ülejäänud aja. Lõbus fakt: 5% kogu ajast kulub DNS-päringutele:

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Aadressid, mida programm otsib, kuuluvad Postgresqli. Kliki FindByAge:

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Huvitaval kombel näitab programm, et põhimõtteliselt on kolm peamist viivitusi lisavat allikat: ühenduste avamine ja sulgemine, andmete küsimine ja andmebaasiga ühenduse loomine. Graafik näitab, et DNS-i päringud, ühenduste avamine ja sulgemine võtavad umbes 13% kogu täitmisajast.

Hüpotees: Ühenduste taaskasutamine puuli abil peaks vähendama ühe HTTP-päringu aega, võimaldades suuremat läbilaskevõimet ja väiksemat latentsust.

Rakenduse seadistamine – katse

Värskendame lähtekoodi, proovime iga päringu puhul eemaldada ühenduse Postgresqliga. Esimene võimalus on kasutada ühendusbassein rakenduse tasemel. Selles katses me paneme selle paika ühenduste ühendamine SQL-draiveri abil:

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

if err != nil {
   return nil, err
}

Teostus, vaatlus, analüüs

Pärast testi taaskäivitamist 1000 päringuga sekundis on selge, et p99 latentsustasemed on 60 ms SLO-ga normaliseerunud!

Mis maksab?

10000 1000 päringut sekundis / 10 päringut serveri kohta = 1 serverit + XNUMX

Teeme seda veelgi paremini!

2000 päringut sekundis

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Koormuse kahekordistamine näitab sama, ülemine vasak graafik näitab, et rakendus suudab töödelda 2000 päringut sekundis, p100 on alla 60 ms, p99 rahuldab SLO.

Kulude osas:

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

3000 päringut sekundis

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Siin saab rakendus töödelda 3000 päringut p99 latentsusajaga alla 60 ms. SLO-d ei rikuta ja kulud aktsepteeritakse järgmiselt:

10000 3000 päringut sekundis / 4 päringu kohta serveri kohta = 1 serverit + XNUMX (autor on ümardanud, u. tõlkija)

Proovime teist analüüsivooru.

Analüüs – hüpotees

Kogume ja kuvame rakenduse silumise tulemusi kiirusega 3000 päringut sekundis:

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Siiski kulub 6% ajast ühenduste loomisele. Puuli seadistamine on parandanud jõudlust, kuid näete siiski, et rakendus jätkab andmebaasiga uute ühenduste loomist.

Hüpotees: Ühendused, hoolimata basseini olemasolust, katkestatakse ja puhastatakse, seega peab rakendus need lähtestama. Ootel olevate ühenduste arvu määramine kogumi suurusele peaks aitama vähendada latentsust, vähendades aega, mis rakendusel ühenduse loomisele kulub.

Rakenduse seadistamine – katse

Proovin installida MaxIdleConns võrdne basseini suurusega (kirjeldatud ka siin):

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

Teostus, vaatlus, analüüs

3000 päringut sekundis

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

p99 on vähem kui 60 ms ja oluliselt vähem p100!

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Leegi graafikut kontrollides on näha, et ühendust pole enam märgata! Kontrollime üksikasjalikumalt pg(*conn).query — me ei märka siin ka ühenduse tekkimist.

SRE: tulemuslikkuse analüüs. Konfigureerimismeetod Go lihtsa veebiserveri abil

Järeldus

Jõudlusanalüüs on ülioluline, et mõista, et klientide ootused ja mittefunktsionaalsed nõuded on täidetud. Analüüs, milles võrreldakse tähelepanekuid klientide ootustega, võib aidata kindlaks teha, mis on vastuvõetav ja mis mitte. Go pakub standardteegi sisseehitatud võimsaid tööriistu, mis muudavad analüüsi lihtsaks ja juurdepääsetavaks.

Allikas: www.habr.com

Lisa kommentaar