SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Našumo analizė ir derinimas yra galingas įrankis, leidžiantis patikrinti, ar klientai laikosi veiklos rezultatų.

Našumo analizė gali būti naudojama norint patikrinti, ar programoje nėra kliūčių, taikant mokslinį požiūrį į derinimo eksperimentų testavimą. Šiame straipsnyje apibrėžiamas bendras požiūris į našumo analizę ir derinimą, kaip pavyzdį naudojant „Go“ žiniatinklio serverį.

„Go“ čia ypač geras, nes turi profiliavimo įrankius pprof standartinėje bibliotekoje.

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

strategija

Sukurkime struktūrinės analizės suvestinį sąrašą. Bandysime panaudoti kai kuriuos duomenis, kad priimtume sprendimus, užuot darę pakeitimus remdamiesi intuicija ar spėlionėmis. Norėdami tai padaryti, atliksime šiuos veiksmus:

  • Nustatome optimizavimo ribas (reikalavimus);
  • Apskaičiuojame transakcijų apkrovą sistemai;
  • Atliekame testą (sukuriame duomenis);
  • Stebime;
  • Analizuojame – ar tenkinami visi reikalavimai?
  • Mes jį nustatome moksliškai, keliame hipotezę;
  • Šiai hipotezei patikrinti atliekame eksperimentą.

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Paprasta HTTP serverio architektūra

Šiam straipsniui naudosime nedidelį HTTP serverį Golange. Visą kodą iš šio straipsnio galite rasti čia.

Analizuojama programa yra HTTP serveris, kuris kiekvieną užklausą apklausia Postgresql. Be to, yra „Prometheus“, „node_exporter“ ir „Grafana“, skirtos programų ir sistemos metrikai rinkti ir rodyti.

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Siekiant supaprastinti, manome, kad horizontaliam mastelio keitimui (ir supaprastinant skaičiavimus) kiekviena paslauga ir duomenų bazė yra diegiamos kartu:

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Tikslų apibrėžimas

Šiame žingsnyje mes apsisprendžiame dėl tikslo. Ką mes bandome analizuoti? Kaip mes žinome, kada laikas baigti? Šiame straipsnyje įsivaizduosime, kad turime klientų ir mūsų paslauga apdoros 10 000 užklausų per sekundę.

В Google SRE knyga Išsamiai aptariami atrankos ir modeliavimo būdai. Padarykime tą patį ir kurkime modelius:

  • Vėlavimas: 99 % užklausų turi būti įvykdytos greičiau nei per 60 ms;
  • Kaina: paslauga turėtų sunaudoti mažiausią pinigų sumą, kuri, mūsų manymu, yra pagrįstai įmanoma. Norėdami tai padaryti, maksimaliai padidiname pralaidumą;
  • Pajėgumų planavimas: reikia suprasti ir dokumentuoti, kiek programos egzempliorių reikės paleisti, įskaitant bendrą mastelio keitimo funkciją ir kiek egzempliorių reikės, kad būtų patenkinti pradiniai įkėlimo ir aprūpinimo reikalavimai. perteklius n+1.

Be analizės gali reikėti optimizuoti delsą, tačiau akivaizdu, kad reikia analizuoti pralaidumą. Naudojant SRE SLO procesą, vėlavimo užklausą pateikia klientas arba įmonė, atstovaujama produkto savininko. Ir mūsų paslauga šį įsipareigojimą vykdys nuo pat pradžių be jokių nustatymų!

Bandymo aplinkos nustatymas

Testinės aplinkos pagalba galėsime įdėti išmatuotą apkrovą mūsų sistemai. Analizei bus generuojami duomenys apie žiniatinklio paslaugos našumą.

Sandorio apkrova

Ši aplinka naudoja vegetuoti Norėdami sukurti pasirinktinį HTTP užklausos greitį iki sustabdymo:

$ 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

Stebėjimas

Operacijos apkrova bus taikoma vykdymo metu. Be programos (užklausų skaičiaus, atsakymo delsos) ir operacinės sistemos (atminties, procesoriaus, IOPS) metrikos, bus vykdomas programos profiliavimas, siekiant suprasti, kur ji turi problemų ir kaip eikvojamas procesoriaus laikas.

Profiliavimas

Profiliavimas yra matavimo tipas, leidžiantis matyti, kur eina procesoriaus laikas, kai programa veikia. Tai leidžia tiksliai nustatyti, kur ir kiek procesoriaus laiko praleidžiama:

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Šie duomenys gali būti naudojami atliekant analizę, kad būtų galima suprasti sugaištą procesoriaus laiką ir atliekamą nereikalingą darbą. Go (pprof) gali generuoti profilius ir vizualizuoti juos kaip liepsnos grafikus, naudodama standartinį įrankių rinkinį. Apie jų naudojimą ir sąrankos vadovą kalbėsiu vėliau šiame straipsnyje.

Vykdymas, stebėjimas, analizė.

Padarykime eksperimentą. Atliksime, stebėsime ir analizuosime tol, kol būsime patenkinti pasirodymu. Pasirinkime savavališkai mažą apkrovos reikšmę, kurią taikysime, kad gautume pirmųjų stebėjimų rezultatus. Kiekviename paskesniame žingsnyje mes padidinsime apkrovą tam tikru mastelio koeficientu, pasirinktu su tam tikra variacija. Kiekvienas apkrovos bandymo paleidimas atliekamas su pakoreguotu užklausų skaičiumi: make load-test LOAD_TEST_RATE=X.

50 užklausų per sekundę

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Atkreipkite dėmesį į dvi viršutines diagramas. Viršuje kairėje rodoma, kad mūsų programa apdoroja 50 užklausų per sekundę (ji mano), o viršuje dešinėje rodoma kiekvienos užklausos trukmė. Abu parametrai padeda mums pažvelgti ir analizuoti, ar esame savo veiklos ribose, ar ne. Raudona linija diagramoje HTTP užklausos delsa rodo SLO esant 60 ms. Linija rodo, kad esame gerokai trumpesni nei maksimalus atsako laikas.

Pažvelkime į išlaidų pusę:

10000 50 užklausų per sekundę / 200 užklausų vienam serveriui = 1 serverių + XNUMX

Dar galime pagerinti šį skaičių.

500 užklausų per sekundę

Įdomesni dalykai pradeda vykti, kai apkrova pasiekia 500 užklausų per sekundę:

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Vėlgi, viršutiniame kairiajame schemoje matote, kad programa įrašo įprastą apkrovą. Jei taip nėra, serveryje, kuriame veikia programa, kilo problema. Atsakymo delsos grafikas yra viršuje dešinėje, rodantis, kad 500 užklausų per sekundę lėmė 25–40 ms atsakymo delsą. 99-asis procentilis vis dar puikiai tinka aukščiau pasirinktam 60 ms SLO.

Kalbant apie išlaidas:

10000 500 užklausų per sekundę / 20 užklausų vienam serveriui = 1 serverių + XNUMX

Viską dar galima patobulinti.

1000 užklausų per sekundę

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Puikus startas! Programa rodo, kad ji apdorojo 1000 užklausų per sekundę, tačiau SLO pažeidė delsos limitą. Tai galima pamatyti p99 eilutėje viršutiniame dešiniajame grafike. Nepaisant to, kad p100 linija yra daug aukštesnė, faktiniai vėlavimai yra didesni nei maksimalus 60 ms. Pasinerkime į profiliavimą, kad sužinotume, ką iš tikrųjų daro programa.

Profiliavimas

Profiliavimui nustatome 1000 užklausų per sekundę apkrovą, tada naudokite pprof fiksuoti duomenis ir sužinoti, kur programa praleidžia procesoriaus laiką. Tai galima padaryti suaktyvinus HTTP galinį tašką pprof, o tada, kai apkrova, išsaugokite rezultatus naudodami curl:

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

Rezultatai gali būti rodomi taip:

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

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Diagrama rodo, kur ir kiek programa praleidžia CPU laiko. Iš aprašymo iš Brendanas Gregas:

X ašis yra krūvos profilio visuma, surūšiuota abėcėlės tvarka (tai ne laikas), Y ašis rodo krūvos gylį, skaičiuojant nuo nulio [viršuje]. Kiekvienas stačiakampis yra krūvos rėmas. Kuo platesnis rėmas, tuo dažniau jis yra rietuvėse. Tai, kas yra viršuje, veikia CPU, o tai, kas yra žemiau, yra antriniai elementai. Spalvos dažniausiai nieko nereiškia, o tiesiog pasirenkamos atsitiktinai, kad atskirtų rėmus.

Analizė – hipotezė

Derindami sutelksime dėmesį į tai, kaip rasti švaistomą procesoriaus laiką. Ieškosime didžiausių nenaudingų išlaidų šaltinių ir juos pašalinsime. Na, o atsižvelgiant į tai, kad profiliavimas labai tiksliai atskleidžia, kur programa praleidžia savo procesoriaus laiką, gali tekti tai padaryti kelis kartus, taip pat reikės pakeisti programos šaltinio kodą, iš naujo atlikti testus ir įsitikinti, kad našumas artėja prie tikslo.

Vadovaudamiesi Brendano Greggo rekomendacijomis, diagramą skaitysime iš viršaus į apačią. Kiekvienoje eilutėje rodomas krūvos rėmelis (funkcijos iškvietimas). Pirmoji eilutė yra įėjimo į programą taškas, visų kitų skambučių pirminė eilutė (kitaip tariant, visi kiti skambučiai turės jį savo krūvoje). Kita eilutė jau kitokia:

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Jei užvedate pelės žymeklį virš funkcijos pavadinimo grafike, bus rodomas bendras laikas, kai ji buvo krūvoje derinimo metu. HTTPServe funkcija buvo 65% laiko, kitos vykdymo funkcijos runtime.mcall, mstart и gc, užėmė likusį laiką. Įdomus faktas: 5% viso laiko praleidžiama DNS užklausoms:

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Adresai, kurių ieško programa, priklauso Postgresql. Spustelėkite FindByAge:

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Įdomu tai, kad programa rodo, kad iš principo yra trys pagrindiniai šaltiniai, kurie prideda vėlavimo: jungčių atidarymas ir uždarymas, duomenų užklausa ir prisijungimas prie duomenų bazės. Diagrama rodo, kad DNS užklausos, jungčių atidarymas ir uždarymas užima apie 13% viso vykdymo laiko.

Hipotezė: Pakartotinis jungčių naudojimas naudojant telkimą turėtų sutrumpinti vienos HTTP užklausos laiką, kad būtų padidintas pralaidumas ir mažesnė delsa.

Programos nustatymas – eksperimentas

Atnaujiname šaltinio kodą, bandome pašalinti ryšį su Postgresql kiekvienai užklausai. Pirmasis variantas yra naudoti prijungimo baseinas taikymo lygiu. Šiame eksperimente mes nustatykime ryšio telkimas naudojant sql tvarkyklę for go:

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

if err != nil {
   return nil, err
}

Vykdymas, stebėjimas, analizė

Iš naujo paleidus testą su 1000 užklausų per sekundę, aišku, kad p99 delsos lygiai grįžo į normalią 60 ms SLO!

Kokia kaina?

10000 1000 užklausų per sekundę / 10 užklausų vienam serveriui = 1 serverių + XNUMX

Padarykime tai dar geriau!

2000 užklausų per sekundę

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Dvigubai apkrova rodo tą patį, viršutinis kairysis grafikas rodo, kad programa sugeba apdoroti 2000 užklausų per sekundę, p100 yra mažesnis nei 60 ms, p99 tenkina SLO.

Kalbant apie išlaidas:

10000 2000 užklausų per sekundę / 5 užklausų vienam serveriui = 1 serverių + XNUMX

3000 užklausų per sekundę

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Čia programa gali apdoroti 3000 užklausų, kurių p99 delsa yra mažesnė nei 60 ms. SLO nepažeidžiamas, o kaina priimama taip:

10000 3000 užklausų per sekundę / 4 1 užklausų vienam serveriui = XNUMX serveriai + XNUMX (autorius suapvalino, apytiksliai vertėjas)

Pabandykime atlikti kitą analizės etapą.

Analizė – hipotezė

Mes renkame ir rodome programos derinimo rezultatus 3000 užklausų per sekundę:

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Vis dar 6% laiko skiriama ryšiams užmegzti. Nustačius telkinį pagerėjo našumas, bet vis tiek matote, kad programa ir toliau kuria naujus ryšius su duomenų baze.

Hipotezė: Nepaisant to, kad yra baseinas, ryšiai vis dar nutraukiami ir išvalomi, todėl programai reikia juos iš naujo nustatyti. Laukiančių jungčių skaičiaus nustatymas pagal telkinio dydį turėtų padėti sumažinti delsą, nes sumažinamas laikas, kurį programa praleidžia kurdama ryšį.

Programos nustatymas – eksperimentas

Bandoma įdiegti MaxIdleConns lygus baseino dydžiui (taip pat aprašyta čia):

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

Vykdymas, stebėjimas, analizė

3000 užklausų per sekundę

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

p99 yra mažesnis nei 60 ms ir žymiai mažesnis p100!

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

Patikrinus liepsnos grafiką matyti, kad ryšio nebepastebi! Patikrinkime išsamiau pg(*conn).query - mes taip pat nepastebime čia užmezgamo ryšio.

SRE: našumo analizė. Konfigūravimo metodas naudojant paprastą žiniatinklio serverį Go

išvada

Veiklos analizė yra labai svarbi norint suprasti, kad klientų lūkesčiai ir nefunkciniai reikalavimai tenkinami. Analizė, lygindama pastebėjimus su klientų lūkesčiais, gali padėti nustatyti, kas yra priimtina, o kas ne. „Go“ teikia galingus įrankius, integruotus į standartinę biblioteką, kurie padaro analizę paprastą ir prieinamą.

Šaltinis: www.habr.com

Добавить комментарий