SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Analýza výkonu a nastavení je mocný nástroj pro ověřování souladu výkonu pro klienty.

Analýza výkonu může být použita k identifikaci úzkých míst v programu s vědeckým přístupem k ověřování experimentů nastavení. Tento článek definuje obecný přístup k analýze výkonu a nastavení s příkladem jednoduchého webového serveru na Go.

Go se zde obzvlášť hodí, protože má nástroje pro profilování pprof ve standardní knihovně.

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Strategie

Vytvořme souhrnný seznam pro naši strukturální analýzu. Pokusíme se použít nějaká data pro rozhodování, místo abychom prováděli změny založené na intuici nebo domněnkách. Pro toto uděláme následující:

  • Definujeme meze optimalizace (požadavky);
  • Vypočítáme transakční zátěž pro systém;
  • Provedeme test (vytvoříme data);
  • Sledujeme;
  • Analyzujeme — jsou dodržována všechna požadavky?
  • Optimalizujeme vědecky, formulujeme hypotézu;
  • Provedeme experiment pro ověření této hypotézy.

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Architektura jednoduchého HTTP serveru

Pro tento článek budeme používat malý HTTP server napsaný v Golangu. Veškerý kód z tohoto článku lze nalézt zde.

Analyzovaná aplikace je HTTP server, který dotazuje Postgresql na každý požadavek. Dále je zde Prometheus, node_exporter a Grafana pro sběr a zobrazení metrik aplikace a systému.

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Pro zjednodušení předpokládejme, že pro horizontální škálování (a zjednodušení výpočtů) jsou všechny služby a databáze nasazovány společně:

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Definujeme cíle

V tomto kroku si definujeme cíl. Co se snažíme analyzovat? Jak poznáme, že je čas skončit? V tomto článku předpokládáme, že máme klienty a náš server bude zpracovávat 10 000 požadavků za sekundu.

V Google SRE Book podrobně prozkoumává metody volby a modelování. Postupujme stejně, postavíme modely:

  • Zpoždění: 99% požadavků by mělo být realizováno za méně než 60 ms;
  • Náklady: služba by měla spotřebovávat minimální částku peněz, kterou považujeme za rozumně možnou. Za tímto účelem maximalizujeme propustnost;
  • Plánování kapacity: je třeba porozumět a zdokumentovat, kolik instancí aplikace bude potřeba spustit, včetně celkové funkce škálování, a také kolik instancí bude nutno pro splnění počátečních požadavků na zátěž a zajištění redundance n+1.

Zpoždění může vyžadovat optimalizaci navíc k analýze, ale propustnost je třeba jasně analyzovat. Při použití procesu SRE SLO vychází požadavek na zpoždění od zákazníka a/nebo podnikání, které zastupuje vlastník produktu. A naše služba bude toto závazek plnit od začátku bez jakýchkoliv úprav!

Nastavení testovacího prostředí

S pomocí testovacího prostředí budeme moci vystavit naší systému dávkovou zátěž. Pro analýzu budou vytvářena data o výkonu webového služby.

Transakční zátěž

Toto prostředí používá Vegeta k vytvoření přizpůsobené frekvence HTTP požadavků, dokud nebude zastaveno:

$ 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

Sledování

Během provádění bude použita transakční zátěž. Kromě metrik aplikace (počet požadavků, zpoždění odpovědi) a operačního systému (paměť, CPU, IOPS) bude spuštěno profilování aplikace, aby se zjistilo, kde v ní jsou problémy, a jak se spotřebovává procesorový čas.

Profilování

Profilování je typ měření, které umožňuje vidět, kam jde procesorový čas během práce aplikace. Umožňuje určit, kde přesně a kolik procesorového času se spotřebovává:

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Tato data lze použít během analýzy, aby se získal přehled o zbytečně utraceném procesorovém čase a prováděné zbytečné práci. Go (pprof) může generovat profily a vizualizovat je jako flame graph, pomocí standardní sady nástrojů. O jejich použití a nastavení se zmíním níže v článku.

Provádění, sledování, analýza.

Provedeme experiment. Budeme vykonávat, pozorovat a analyzovat, dokud nás výkon neuspokojí. Vybereme náhodně nízkou úroveň zátěže, abychom ji použili pro získání výsledků prvních pozorování. Na každém dalším kroku budeme zátěž zvyšovat s určitým škálovacím koeficientem vybraným s jistým rozptylem. Každé spuštění zátěžového testování se provádí s úpravou počtu požadavků: make load-test LOAD_TEST_RATE=X.

50 požadavků za sekundu

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Všimněte si dvou horních grafů. Horní levý ukazuje, že naše aplikace zpracovává 50 požadavků za sekundu (podle jejího názoru), a horní pravý – dobu trvání každého požadavku. Oba parametry nám pomáhají pozorovat a analyzovat: zda se vejdeme do našich výkonových limitů nebo ne. Červená čára na grafu HTTP Request Latency ukazuje SLO na 60ms. Z čáry je vidět, že jsme daleko pod naším maximálním časem odpovědi.

Podívejme se z pohledu nákladů:

10000 požadavků za sekundu / na 50 požadavků na server = 200 serverů + 1

Stále můžeme tento údaj zlepšit.

500 požadavků za sekundu

Zajímavější věci začínají nastávat, když zatížení dosáhne 500 požadavků za sekundu:

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Opět na levém horním grafu je vidět, že aplikace zaznamenává běžnou zátěž. Pokud tomu tak není, je na serveru, na kterém je aplikace spuštěna, problém. Graf se zpožděním odpovědi je umístěn nahoře vpravo a ukazuje, že 500 požadavků za sekundu vedlo k zpoždění odpovědi v rozmezí 25-40ms. 99. percentil se stále skvěle vejde do SLO 60ms, který byl zvolen výše.

Z pohledu nákladů:

10000 požadavků za sekundu / na 500 požadavků na server = 20 serverů + 1

Stále je možné zlepšit.

1000 požadavků za sekundu

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Skvělé spuštění! Aplikace ukazuje, že zpracovala 1000 požadavků za sekundu, avšak hranice zpoždění byla porušena z pohledu SLO. To je vidět podle čáry p99 na pravém horním grafu. I když je čára p100 mnohem výš, skutečná zpoždění překračují maximum 60ms. Pojďme se ponořit do profilování, abychom zjistili, co aplikace skutečně dělá.

Profilování

Pro profilování nasadíme zátěž na 1000 požadavků za sekundu, poté použijeme pprof k získání dat a zjistíme, kde aplikace tráví procesorový čas. To lze provést aktivací HTTP endpoint pprof, po kterém se při zátěži uloží výsledky pomocí curl:

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

Výsledky mohou být zobrazeny takto:

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

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Graf ukazuje, kde a kolik procesorového času aplikace utrácí. Z popisu od Brendan Gregg:

Na ose X je vyplnění zásobníku, seřazené abecedně (to není čas), osa Y ukazuje hloubku zásobníku, počítáno od nuly v [top]. Každý obdélník představuje rámec zásobníku. Čím širší je rámec, tím častěji se objevuje ve stacích. To, co je nahoře, využívá CPU, a níže jsou podřízené prvky. Barvy obvykle nic neznamenají a jsou vybírány náhodně pro odlišení rámců.

Analýza — hypotéza

Při nastavení se zaměříme na pokus najít neužitečné plýtvání procesorovým časem. Budeme hledat největší zdroje neužitečného plýtvání a odstraníme je. S ohledem na to, že profilování velmi přesně odhaluje, kde aplikace utrácí svůj procesorový čas, možná bude nutné to udělat několikrát a bude nutné měnit zdrojový kód aplikace, restartovat testy a sledovat, jak se výkon blíží plánovanému.

Podle doporučení Brendana Gregga budeme číst graf shora dolů. Každý řádek zobrazuje rámec zásobníku (volání funkce). První řádek je vstupní bod programu, rodič všech ostatních volání (jinými slovy všechna ostatní volání budou mít jeho ve svém zásobníku). Další řádek se již liší:

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Pokud najedete kurzorem na název funkce na grafu, zobrazí se celkový čas, který byla ve zásobníku během ladění. Funkce HTTPServe byla zde 65% času, jiné funkce runtime, runtime.mcall, mstart a gc, spotřebovaly zbytek času. Zajímavý fakt: 5% celkového času bylo vynaloženo na dotazy na DNS:

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Adresy, které program hledá, patří Postgresql. Klikneme na FindByAge:

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Zajímavé je, že program ukazuje, že existují tři hlavní zdroje, které přidávají zpoždění: otevírání a zavírání připojení, dotazy na data a připojení k databázi. Na grafu je vidět, že dotazy na DNS, otevírání a zavírání připojení zabírají přibližně 13% celkového času vykonávání.

Hypotéza: Opětovné použití spojení pomocí poolu by mělo zkrátit dobu jednoho HTTP požadavku, což umožní vyšší propustnost a nižší latenci..

Nastavení aplikace — experiment.

Aktualizujeme zdrojový kód, zkoušíme odstranit spojení s Postgresql na každý požadavek. První varianta — použití poolu spojení na úrovni aplikace. V tomto experimentu si nastavíme pool spojení pomocí SQL ovladače pro Go:

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

if err != nil {
   return nil, err
}

Provádění, sledování, analýza.

Po restartu testu se 1000 požadavky za sekundu je vidět, že p99 latence se dostala na normu se SLO 60ms!

Jak je to se náklady?

10000 požadavků za sekundu / na 1000 požadavků na server = 10 serverů + 1.

Pojďme to udělat ještě lépe!

2000 požadavků za sekundu.

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Dvojnásobné zatížení ukazuje totéž, levý horní graf demonstruje, že aplikace zvládá 2000 požadavků za sekundu, p100 pod 60ms, p99 splňuje SLO.

Z pohledu nákladů:

10000 požadavků za sekundu / na 2000 požadavků na server = 5 serverů + 1.

3000 požadavků za sekundu.

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Zde aplikace může zpracovat 3000 požadavků s latencí p99 pod 60ms. SLO není narušeno a náklady byly přijaté takto:

10000 požadavků za sekundu / na 3000 požadavků na server = 4 servery + 1. (autor zaokrouhlil na větší, pozn. překladatele)

Pojďme zkusit další kolo analýzy.

Analýza — hypotéza

Skrýváme a zobrazuje výsledky ladění aplikace na 3000 požadavků za sekundu:

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Stále 6 % času se tráví na vytváření spojení. Nastavení poolu zlepšilo výkon, ale stále je vidět, že aplikace pokračuje ve vytváření nových spojení s databází.

Hypotéza: Spojení, navzdory existenci poolu, jsou stále odmítána a odstraňována, proto aplikaci je nutné je znovu navázat. Nastavení počtu čekajících spojení na velikost poolu by mělo pomoci se zpožděním tím, že minimalizuje čas, který aplikace tráví vytvářením spojení..

Nastavení aplikace — experiment.

Zkoušíme nastavit MaxIdleConns na velikost poolu (také popsáno zde):

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

Provádění, sledování, analýza.

3000 požadavků za sekundu.

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

p99 pod 60ms s výrazně nižším p100!

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Kontrola flame graph ukazuje, že nastavení spojení již není patrné! Kontrolujeme podrobněji. pg(*conn).query — také zde nenacházíme nastavení spojení.

SRE: Analýza výkonu. Metoda nastavení pomocí jednoduchého webového serveru na Go

Závěr

Analýza výkonnosti je klíčová pro pochopení toho, zda jsou splněny očekávání zákazníků a nefunkční požadavky. Analýza porovnáváním pozorování s očekáváními zákazníků může pomoci určit, co je přijatelné a co ne. Go poskytuje efektivní nástroje, které jsou součástí standardní knihovny, díky nimž je analýza jednoduchá a dostupná.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster