SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Analýza a ladenie výkonu je výkonný nástroj na overenie súladu s výkonom pre klientov.

Analýza výkonu sa môže použiť na kontrolu úzkych miest v programe uplatnením vedeckého prístupu k testovaniu experimentov ladenia. Tento článok definuje všeobecný prístup k analýze a ladeniu výkonu, pričom ako príklad používa webový server Go.

Go je tu obzvlášť dobrý, pretože má nástroje na profilovanie pprof v štandardnej knižnici.

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

stratégia

Vytvorme súhrnný zoznam pre našu štrukturálnu analýzu. Pokúsime sa použiť niektoré údaje na rozhodovanie namiesto vykonávania zmien na základe intuície alebo dohadov. Aby sme to urobili, urobíme toto:

  • Stanovíme hranice optimalizácie (požiadavky);
  • Vypočítame transakčné zaťaženie pre systém;
  • Vykonávame test (vytvárame údaje);
  • Pozorujeme;
  • Analyzujeme - sú splnené všetky požiadavky?
  • Stanovili sme to vedecky, vytvorili hypotézu;
  • Vykonávame experiment na overenie tejto hypotézy.

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Jednoduchá architektúra HTTP servera

Pre tento článok použijeme malý HTTP server v Golangu. Celý kód z tohto článku nájdete tu.

Analyzovaná aplikácia je HTTP server, ktorý pre každú požiadavku zisťuje Postgresql. Okrem toho existuje Prometheus, node_exporter a Grafana na zhromažďovanie a zobrazovanie metrík aplikácií a systému.

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Pre zjednodušenie uvažujeme, že pre horizontálne škálovanie (a zjednodušenie výpočtov) sa každá služba a databáza nasadzujú spoločne:

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Definovanie cieľov

V tomto kroku sa rozhodujeme o cieli. Čo sa snažíme analyzovať? Ako vieme, kedy je čas skončiť? V tomto článku si predstavíme, že máme klientov a že naša služba spracuje 10 000 požiadaviek za sekundu.

В Google SRE Book Metódy výberu a modelovania sú podrobne diskutované. Urobme to isté a zostavme modely:

  • Latencia: 99 % žiadostí by malo byť dokončených za menej ako 60 ms;
  • Cena: Služba by mala spotrebovať minimálne množstvo peňazí, ktoré je podľa nás primerane možné. Aby sme to dosiahli, maximalizujeme priepustnosť;
  • Plánovanie kapacity: Vyžaduje pochopenie a zdokumentovanie, koľko inštancií aplikácie bude potrebné spustiť, vrátane celkovej funkcie škálovania a koľko inštancií bude potrebných na splnenie požiadaviek na počiatočné zaťaženie a poskytovanie. redundancia n+1.

Latencia môže vyžadovať okrem analýzy aj optimalizáciu, ale je potrebné jednoznačne analyzovať priepustnosť. Pri použití procesu SRE SLO prichádza žiadosť o oneskorenie od zákazníka alebo firmy, ktorú zastupuje vlastník produktu. A túto povinnosť naša služba splní už od začiatku bez akéhokoľvek nastavovania!

Nastavenie testovacieho prostredia

Pomocou testovacieho prostredia budeme môcť na náš systém umiestniť meranú záťaž. Na analýzu sa vygenerujú údaje o výkone webovej služby.

Transakčné zaťaženie

Toto prostredie využíva vegetovať na vytvorenie vlastnej rýchlosti požiadaviek HTTP až do zastavenia:

$ 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

Transakčné zaťaženie sa použije za behu. Okrem metrík aplikácie (počet požiadaviek, latencia odozvy) a operačného systému (pamäť, CPU, IOPS) sa spustí profilovanie aplikácií, aby sme pochopili, kde má problémy a ako sa spotrebúva čas CPU.

Profilovanie

Profilovanie je typ merania, ktorý vám umožňuje zistiť, kam ide čas procesora, keď je aplikácia spustená. Umožňuje vám presne určiť, kde a koľko času procesora strávi:

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Tieto údaje je možné použiť počas analýzy na získanie prehľadu o stratenom CPU a zbytočnej vykonávanej práci. Go (pprof) dokáže generovať profily a vizualizovať ich ako plameňové grafy pomocou štandardnej sady nástrojov. O ich použití a sprievodcovi nastavením sa porozprávam neskôr v článku.

Prevedenie, pozorovanie, rozbor.

Urobme experiment. Budeme vykonávať, pozorovať a analyzovať, kým nebudeme spokojní s výkonom. Vyberme si ľubovoľne nízku hodnotu zaťaženia, aby sme ju použili na získanie výsledkov prvých pozorovaní. V každom nasledujúcom kroku zvýšime zaťaženie s určitým škálovacím faktorom, zvoleným s určitou obmenou. Každý test záťaže sa vykonáva s upraveným počtom požiadaviek: make load-test LOAD_TEST_RATE=X.

50 žiadostí za sekundu

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Venujte pozornosť horným dvom grafom. Vľavo hore ukazuje, že naša aplikácia spracuje 50 požiadaviek za sekundu (myslí) a vpravo hore je zobrazená dĺžka trvania každej požiadavky. Oba parametre nám pomáhajú pozerať sa a analyzovať, či sme v rámci svojich výkonnostných hraníc alebo nie. Červená čiara na grafe Latencia požiadavky HTTP ukazuje SLO pri 60 ms. Čiara ukazuje, že sme hlboko pod naším maximálnym časom odozvy.

Pozrime sa na nákladovú stránku:

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

Toto číslo môžeme ešte zlepšiť.

500 žiadostí za sekundu

Zaujímavejšie veci sa začnú diať, keď zaťaženie dosiahne 500 požiadaviek za sekundu:

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Opäť v ľavom hornom grafe vidíte, že aplikácia zaznamenáva bežné zaťaženie. Ak to tak nie je, vyskytol sa problém na serveri, na ktorom je aplikácia spustená. Graf latencie odozvy sa nachádza vpravo hore a ukazuje, že 500 žiadostí za sekundu viedlo k oneskoreniu odozvy 25 – 40 ms. 99. percentil stále dobre zapadá do vyššie zvoleného 60 ms SLO.

Z hľadiska nákladov:

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

Všetko sa dá ešte zlepšiť.

1000 žiadostí za sekundu

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Skvelé spustenie! Aplikácia ukazuje, že spracovala 1000 požiadaviek za sekundu, ale limit latencie bol porušený SLO. To je možné vidieť na riadku p99 v grafe vpravo hore. Napriek tomu, že riadok p100 je oveľa vyšší, skutočné oneskorenia sú vyššie ako maximum 60 ms. Poďme sa ponoriť do profilovania, aby sme zistili, čo vlastne aplikácia robí.

Profilovanie

Pre profilovanie nastavíme zaťaženie na 1000 XNUMX požiadaviek za sekundu a potom použijeme pprof na zachytávanie údajov, aby ste zistili, kde aplikácia trávi čas procesora. To sa dá dosiahnuť aktiváciou koncového bodu HTTP pprofa potom pri zaťažení uložte výsledky pomocou curl:

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

Výsledky je možné zobraziť takto:

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

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Graf ukazuje, kde a koľko aplikácia trávi procesorový čas. Z popisu od Brendan Gregg:

Os X je populácia profilu zásobníka zoradená abecedne (toto nie je čas), os Y zobrazuje hĺbku zásobníka, počítajúc od nuly hore [hore]. Každý obdĺžnik je stohovaný rám. Čím širší je rám, tým častejšie je prítomný v hromadách. To, čo je hore, beží na CPU a to, čo je nižšie, sú podradené prvky. Farby zvyčajne nič neznamenajú, ale sú jednoducho vybrané náhodne, aby odlíšili rámy.

Analýza - hypotéza

Pri ladení sa zameriame na hľadanie strateného času CPU. Budeme hľadať najväčšie zdroje zbytočných výdavkov a odstránime ich. Vzhľadom na to, že profilovanie veľmi presne odhaľuje, kde presne aplikácia trávi čas procesora, možno to budete musieť urobiť niekoľkokrát a budete tiež musieť zmeniť zdrojový kód aplikácie, znova spustiť testy a uvidíte, že výkon sa blíži k cieľu.

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

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Ak umiestnite kurzor myši na názov funkcie v grafe, zobrazí sa celkový čas, počas ktorého bola v zásobníku počas ladenia. Funkcia HTTPServe tam bola 65% času, ostatné runtime funkcie runtime.mcall, mstart и gc, zabralo zvyšok času. Zaujímavý fakt: 5 % z celkového času sa vynakladá na dotazy DNS:

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

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

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Je zaujímavé, že program ukazuje, že v zásade existujú tri hlavné zdroje, ktoré pridávajú oneskorenia: otváranie a zatváranie spojení, vyžiadanie údajov a pripojenie k databáze. Graf ukazuje, že požiadavky DNS, otváranie a zatváranie spojení zaberajú približne 13 % z celkového času vykonávania.

hypotéza: Opätovné použitie pripojení pomocou združovania by malo skrátiť čas jednej požiadavky HTTP, čo umožní vyššiu priepustnosť a nižšiu latenciu.

Nastavenie aplikácie - experiment

Aktualizujeme zdrojový kód, snažíme sa odstrániť pripojenie k Postgresql pre každú požiadavku. Prvou možnosťou je použiť bazén pripojenia na aplikačnej úrovni. V tomto experimente sme poďme to nastaviť združovanie pripojení pomocou ovládača sql for go:

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

if err != nil {
   return nil, err
}

Prevedenie, pozorovanie, rozbor

Po reštartovaní testu s 1000 požiadavkami za sekundu je jasné, že úrovne latencie p99 sa vrátili do normálu s SLO 60 ms!

Aké sú náklady?

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

Urobme to ešte lepšie!

2000 žiadostí za sekundu

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Zdvojnásobenie záťaže ukazuje to isté, ľavý horný graf ukazuje, že aplikácia zvláda spracovať 2000 požiadaviek za sekundu, p100 je nižšie ako 60 ms, p99 spĺňa SLO.

Z hľadiska nákladov:

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

3000 žiadostí za sekundu

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Tu aplikácia dokáže spracovať 3000 požiadaviek s latenciou p99 menšou ako 60 ms. SLO nie je porušené a náklady sa akceptujú takto:

10000 3000 požiadaviek za sekundu / na 4 1 požiadaviek na server = XNUMX servery + XNUMX (autor zaokrúhlil nahor, približne. prekladateľ)

Skúsme ďalšie kolo analýzy.

Analýza - hypotéza

Zhromažďujeme a zobrazujeme výsledky ladenia aplikácie rýchlosťou 3000 XNUMX žiadostí za sekundu:

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Stále 6 % času strávime nadväzovaním spojení. Nastavenie fondu zlepšilo výkon, ale stále môžete vidieť, že aplikácia naďalej pracuje na vytváraní nových pripojení k databáze.

hypotéza: Pripojenia, napriek prítomnosti fondu, sú stále zrušené a vyčistené, takže ich aplikácia musí resetovať. Nastavenie počtu čakajúcich pripojení na veľkosť fondu by malo pomôcť s latenciou minimalizovaním času, ktorý aplikácia strávi vytváraním pripojenia.

Nastavenie aplikácie - experiment

Pokúšam sa nainštalovať MaxIdleConns rovná veľkosti bazéna (tiež popísané tu):

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

Prevedenie, pozorovanie, rozbor

3000 žiadostí za sekundu

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

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

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Kontrola grafu plameňa ukazuje, že spojenie už nie je viditeľné! Pozrime sa podrobnejšie pg(*conn).query — tiež si nevšimneme, že sa tu vytvára spojenie.

SRE: Analýza výkonnosti. Spôsob nastavenia pomocou jednoduchého webového servera v Go

Záver

Analýza výkonnosti je rozhodujúca pre pochopenie toho, že očakávania zákazníkov a nefunkčné požiadavky sú splnené. Analýza porovnaním pozorovaní s očakávaniami zákazníkov môže pomôcť určiť, čo je prijateľné a čo nie. Go poskytuje výkonné nástroje zabudované do štandardnej knižnice, vďaka ktorým je analýza jednoduchá a prístupná.

Zdroj: hab.com

Pridať komentár