SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Analýza výkonu a optimalizácia – výkonný nástroj na overenie zhodnosti výkonu pre klientov.

Analýzu výkonu je možné využiť na identifikáciu úzkych miest v programe, pričom použijeme vedecký prístup k overovaniu pokusov o optimalizáciu. Tento článok určuje všeobecný prístup k analýze výkonu a optimalizácii na príklade webového servera na Go.

Go je tu obzvlášť vhodné, pretože obsahuje nástroje na profilovanie. pprof v štandardnej knižnici.

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Stratégia

Vytvorme súhrnný zoznam pre našu štrukturálnu analýzu. Pokúsime sa využiť niektoré údaje na rozhodovanie namiesto toho, aby sme vykonávali zmeny na základe intuícií alebo domnienok. Urobíme to takto:

  • Definujeme hranice optimalizácie (požiadavky);
  • Vypočítame transakčnú záťaž pre systém;
  • Vykonáme test (vytvoríme údaje);
  • Pozorujeme;
  • Analyzujeme – dodržiavajú sa všetky požiadavky?
  • Optimalizujeme vedecky, formulujeme hypotézu;
  • Vykonáme experiment na overenie tejto hypotézy.

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Architektúra jednoduchého HTTP servera

Pre tento článok budeme používať malý HTTP server na Golangu. Celý kód z tohto článku nájdete tu.

Analyzovaná aplikácia je HTTP server, ktorý dotazuje PostgreSQL na každý požiadavok. Okrem toho sú k dispozícii Prometheus, node_exporter a Grafana na zhromažďovanie a zobrazenie metrik aplikácie a systému.

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Na zjednodušenie predpokladajme, že pre horizontálne škálovanie (a zjednodušenie výpočtov) sú každý servis a databáza nasadené spolu:

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Definujeme ciele

V tomto kroku definujeme cieľ. Čo sa snažíme analyzovať? Ako zistíme, kedy skončiť? V tomto článku predpokladáme, že máme klientov a že náš servis bude zpracovávať 10 000 požiadaviek za sekundu.

V Google SRE Book podrobne sú prebrané spôsoby voľby a modelovania. Postupujeme rovnako, vytvoríme modely:

  • Zdržanie: 99 % požiadaviek by sa malo vykonať za menej ako 60 ms;
  • Náklady: služba by mala spotrebovať minimálnu sumu peňazí, ktorú považujeme za rozumne možnú. Na to maximalizujeme priepustnosť;
  • Plánovanie kapacít: je potrebné pochopiť a zdokumentovať, koľko inštancií aplikácie bude potrebné spustiť, vrátane celkovej funkcie škálovania, ako aj koľko inštancií bude potrebných na splnenie počiatočných požiadaviek na záťaž a zabezpečenie prebytok n+1.

Zdržanie môže vyžadovať optimalizáciu vedľa analýzy, no priepustnosť je potrebné jasne analyzovať. Pri použití procesu SRE SLO požiadavka na zdržanie vychádza od klienta a/alebo podnikania, zastúpeného vlastníkom produktu. A naša služba bude plniť tento záväzok od samého začiatku bez akýchkoľvek nastavení!

Nastavenie testovacieho prostredia

S pomocou testovacieho prostredia budeme môcť generovať dávkovú záťaž na našom systéme. Na analýzu sa budú vytvárať údaje o výkonnosti webovej služby.

Transakčná záťaž

Toto prostredie používa Vegeta na vytvorenie prispôsobenej frekvencie požiadaviek cez HTTP, kým sa nezastaví:

$ 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

Sledovanie

Počas vykonávania bude aplikovaná transakčná záťaž. Okrem metriky aplikácie (počet požiadaviek, zdržanie pri odpovedi) a operačného systému (pamäť, CPU, IOPS) sa spustí profilovanie aplikácie, aby sme pochopili, kde sú v nej problémy, ako aj ako sa spotrebúva procesorový čas.

Profilovanie

Profilovanie je typ merania, ktorý umožňuje vidieť, kam ide procesorový čas pri práci aplikácie. Umožňuje určiť, kde presne a koľko ide procesorového času:

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Tieto údaje môžu byť použité počas analýzy, aby sa získal prehľad o zbytočne vynaloženom procesorovom čase a vykonávanej zbytočnej práci. Go (pprof) môže generovať profily a vizualizovať ich ako flame graph, pomocou štandardnej sady nástrojov. O ich používaní a sprievodcovi nastavením sa dozviete nižšie v článku.

Vykonávanie, sledovanie, analýza.

Urobíme experiment. Budeme vykonávať, pozorovať a analyzovať, kým nebudeme s výkonnosťou spokojní. Zvolíme náhodne nízku úroveň záťaže, aby sme ju použili na získanie výsledkov prvých pozorovaní. Na každom ďalšom kroku budeme zvyšovať záťaž s určitým koeficientom škálovania, vybraným s určitým rozptýlením. Každé spustenie záťažového testovania sa vykonáva s úpravou počtu požiadaviek: make load-test LOAD_TEST_RATE=X.

50 požiadaviek za sekundu

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Všimnite si dva horné grafy. Horný ľavý ukazuje, že naša aplikácia spracováva 50 požiadaviek za sekundu (podľa jej názoru), a horný pravý — trvanie každej požiadavky. Oba parametre nám pomáhajú sledovať a analyzovať: či sa zmestíme do našich hraníc výkonu alebo nie. Červená línia na grafe HTTP Request Latency ukazuje SLO na 60 ms. Na línii je vidieť, že sme omnoho pod naším maximálnym časom odpovede.

Pozrime sa z pohľadu nákladov:

10000 požiadaviek za sekundu / na 50 požiadaviek na server = 200 serverov + 1

Stále môžeme tento ukazovateľ zlepšiť.

500 požiadaviek za sekundu

Zaujímavé veci sa začínajú diať, keď záťaž dosiahne 500 požiadaviek za sekundu:

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Opäť na hornom ľavom grafe je vidieť, že aplikácia zaznamenáva bežnú záťaž. Ak to tak nie je — je problém na serveri, na ktorom je aplikácia spustená. Graf s oneskorením odpovede sa nachádza hore vpravo, ukazuje, že 500 požiadaviek za sekundu viedlo k oneskoreniu odpovede v rozmedzí 25-40 ms. 99. percentil sa stále skvele zmestí do SLO 60 ms, vybraného vyššie.

Z pohľadu nákladov:

10000 požiadaviek za sekundu / na 500 požiadaviek na server = 20 serverov + 1

Stále je priestor na zlepšenie.

1000 požiadaviek za sekundu

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Skvelý štart! Aplikácia ukazuje, že spracovala 1000 požiadaviek za sekundu, avšak hranica oneskorenia bola prekročená zo strany SLO. To je vidieť na línii p99 na hornom pravom grafe. Napriek tomu, že línia p100 je omnoho vyššia, skutočné oneskorenia sú nad maximom 60 ms. Poďme sa ponoriť do profilovania, aby sme zistili, čo aplikácia naozaj robí.

Profilovanie

Na profilovanie nastavíme záťaž na 1000 požiadaviek za sekundu, potom použijeme pprof na zhromaždenie údajov, aby sme zistili, kde aplikácia trávi procesorový čas. To sa dá urobiť aktivovaním HTTP endpointu pprof, po ktorom pri zaťažení uložíme výsledky pomocou curl:

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

Výsledky môžu byť zobrazené takto:

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

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Graf zobrazuje, kde a koľko procesorového času aplikácia utráca. Z opisu od Brendan Gregg:

Na osi X je vyplnenie profilu zásobníka, zoradené abecedne (to nie je čas), os Y zobrazuje hĺbku zásobníka, počítanú od nuly v [top]. Každý rectangle je rámec zásobníka. Čím širší rámec, tým častejšie sa vyskytuje v zásobníkoch. To, čo je navrch — pracuje na CPU, a nižšie — podriadené prvky. Farby zvyčajne nič neznamenajú, iba sa náhodne vyberajú na odlíšenie rámcov.

Analýza — hypotéza

Pre nastavenie sa zameriame na hľadanie zbytočného utrácania procesorového času. Budeme hľadať najväčšie zdroje zbytočných výdavkov a odstraňovať ich. Berúc do úvahy, že profilovanie veľmi presne odhaľuje, kde presne aplikácia utráca svoj procesorový čas, možno to bude potrebné zopakovať niekoľkokrát a tiež bude potrebné upraviť zdrojový kód aplikácie, reštartovať testy a sledovať, či sa výkon približuje k plánovanej hodnote.

Podľa odporúčaní Brendana Gregga budeme čítať graf zhora nadol. Každý riadok zobrazuje rámec zásobníka (volanie funkcie). Prvý riadok je vstupný bod do programu, rodič všetkých ostatných volaní (inými slovami, všetky ostatné volania ho budú mať vo svojom zásobníku). Ďalší riadok sa už líši:

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Ak umiestnite kurzor na názov funkcie na grafe — zobrazuje sa celkový čas, počas ktorého bola v zásobníku počas ladenia. Funkcia HTTPServe tam bola 65% času, ostatné funkcie runtime, runtime.mcall, mstart a gc, zaberali zvyšok času. Zaujímavý fakt: 5% celkového času bolo vynaložených na požiadavky na DNS:

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Adresy, ktoré program hľadá, patria Postgresql. Klikneme na FindByAge:

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Zaujímavé, program ukazuje, že v zásade existujú tri hlavné zdroje, ktoré pridávajú oneskorenia: otváranie a zatváranie pripojení, dotazy na údaje a pripojenie k databáze. Na grafe je vidieť, že požiadavky na DNS, otváranie a zatváranie pripojení zaberajú približne 13% celkového času vykonania.

Hipotéza: Znovupoužitie spojení prostredníctvom poolu by malo znížiť čas jedného HTTP požiadavku, čo umožní vyššiu priepustnosť a nižšie oneskorenia..

Nastavenie aplikácie — experiment.

Aktualizujeme zdrojový kód, snažíme sa odstrániť spojenie s PostgreSQL pri každom požiadavku. Prvá možnosť — použitie poolu spojení na úrovni aplikácie. V tomto experimente nastavíme pool spojení pomocou ovládača SQL pre Go:

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

if err != nil {
   return nil, err
}

Realizácia, monitoring, analýza.

Po opätovnom spustení testu s 1000 požiadavkami za sekundu je zrejmé, že p99 latencie sa vrátil do normálu so SLO 60ms!

A čo cena?

10000 požiadaviek za sekundu / 1000 požiadaviek na server = 10 serverov + 1

Poďme to ešte zlepšiť!

2000 požiadaviek za sekundu.

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Zdvojenie zaťaženia ukazuje to isté, ľavý horný graf naznačuje, že aplikácia dokáže spracovať 2000 požiadaviek za sekundu, p100 je pod 60ms, p99 spĺňa SLO.

Z pohľadu nákladov:

10000 požiadaviek za sekundu / 2000 požiadaviek na server = 5 serverov + 1

3000 požiadaviek za sekundu.

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Aplikácia tu dokáže spracovať 3000 požiadaviek so oneskorením p99 menej ako 60ms. SLO nie je porušené, a cena bola stanovená takto:

10000 požiadaviek za sekundu / 3000 požiadaviek na server = 4 servery + 1 (autor zaokrúhľuje na väčšie, pozn. prekladateľa)

Poďme vyskúšať ešte jedno kolo analýzy.

Analýza — hypotéza

Zhromažďujeme a zobrazujeme výsledky ladenia aplikácie pri 3000 požiadavkách za sekundu:

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Stále sa 6% času trávi vytváraním spojení. Nastavenie poolu zlepšilo výkon, ale stále je viditeľné, že aplikácia sa naďalej zaoberá vytváraním nových spojení s databázou.

Hipotéza: Spojenia, napriek existencii poolu, sú stále zamietané a čistené, takže aplikácia ich musí znovu vytvárať. Nastavenie počtu čakajúcich spojení rovná sa veľkosti poolu by malo pomôcť s oneskorením tým, že minimalizuje čas, ktorý aplikácia strávi vytváraním spojenia..

Nastavenie aplikácie — experiment.

Snažíme sa nastaviť MaxIdleConns rovnému rozmeru poolu (tiež je opísané tu):

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

Realizácia, monitoring, analýza.

3000 požiadaviek za sekundu.

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

p99 je menej ako 60ms s výrazne menším p100!

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Kontrola flame grafu ukazuje, že nastavenie spojenia už nie je viditeľné! Skontrolujeme podrobnejšie pg(*conn).query — tu tiež nezaznamenávame nastavenie spojenia.

SRE: Analýza výkonu. Spôsob nastavenia s použitím jednoduchého webového servera na Go

Záver

Analýza výkonu je kľúčová pre pochopenie toho, či sú splnené očakávania zákazníkov a nefunkčné požiadavky. Analýza porovnávaním pozorovaní s očakávaniami zákazníkov môže pomôcť určiť, čo je prijateľné a čo nie. Go poskytuje účinné nástroje zabudované v štandardnej knižnici, pomocou ktorých môže byť analýza jednoduchá a dostupná.

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster