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

Analýza a ladění výkonu je výkonným nástrojem pro ověřování souladu výkonu pro klienty.

Analýzu výkonu lze použít ke kontrole úzkých míst v programu použitím vědeckého přístupu k testování experimentů ladění. Tento článek definuje obecný přístup k analýze a ladění výkonu, jako příklad používá webový server Go.

Go je zde obzvláště dobrý, protože má nástroje pro profilování pprof ve standardní knihovně.

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

strategie

Vytvořme souhrnný seznam pro naši statickou analýzu. Pokusíme se použít některá data k rozhodování namísto provádění změn na základě intuice nebo odhadů. K tomu provedeme toto:

  • Stanovíme hranice optimalizace (požadavky);
  • Vypočítáme transakční zatížení pro systém;
  • Provedeme test (vytvoříme data);
  • Pozorujeme;
  • Analyzujeme - jsou splněny všechny požadavky?
  • Stanovili jsme to vědecky, vytvořili jsme hypotézu;
  • Provádíme experiment, abychom tuto hypotézu ověřili.

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

Jednoduchá architektura HTTP serveru

Pro tento článek použijeme malý HTTP server v Golangu. Celý kód z tohoto článku lze nalézt zde.

Analyzovaná aplikace je HTTP server, který se dotazuje Postgresql pro každý požadavek. Kromě toho existuje Prometheus, node_exporter a Grafana pro shromažďování a zobrazování metrik aplikací a systému.

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

Pro zjednodušení uvažujeme, že pro horizontální škálování (a zjednodušení výpočtů) jsou každá služba a databáze nasazeny společně:

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

Definování cílů

V tomto kroku rozhodujeme o cíli. Co se snažíme analyzovat? Jak poznáme, že je čas skončit? V tomto článku si představíme, že máme klienty a že naše služba zpracuje 10 000 požadavků za sekundu.

В Google SRE Book Podrobně jsou diskutovány metody výběru a modelování. Udělejme totéž a sestavme modely:

  • Latence: 99 % požadavků by mělo být dokončeno za méně než 60 ms;
  • Cena: Služba by měla spotřebovat minimální množství peněz, které je podle nás rozumně možné. Abychom toho dosáhli, maximalizujeme propustnost;
  • Plánování kapacity: Vyžaduje pochopení a dokumentaci, kolik instancí aplikace bude potřeba spustit, včetně celkové funkce škálování, a kolik instancí bude potřeba ke splnění požadavků na počáteční zatížení a zřizování. redundance n+1.

Latence může kromě analýzy vyžadovat optimalizaci, ale propustnost je jednoznačně potřeba analyzovat. Při použití procesu SRE SLO přichází požadavek na zpoždění od zákazníka nebo firmy, kterou zastupuje vlastník produktu. A tuto povinnost naše služba splní od samého začátku bez jakéhokoli nastavování!

Nastavení testovacího prostředí

Pomocí testovacího prostředí budeme schopni umístit naměřenou zátěž na náš systém. Pro analýzu budou vygenerována data o výkonu webové služby.

Transakční zatížení

Toto prostředí využívá vegetovat vytvořit vlastní rychlost požadavků HTTP, dokud nebude zastavena:

$ 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

Pozorování

Transakční zatížení bude aplikováno za běhu. Kromě metrik aplikace (počet požadavků, latence odezvy) a operačního systému (paměť, CPU, IOPS) bude spuštěno profilování aplikací, aby se zjistilo, kde má problémy a jak se spotřebovává čas CPU.

Profilování

Profilování je typ měření, který vám umožňuje zjistit, kam běží čas CPU, když je aplikace spuštěna. Umožňuje přesně určit, kde a kolik času procesoru stráví:

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

Tato data lze použít během analýzy k získání přehledu o plýtvání časem CPU a zbytečné práci, která se provádí. Go (pprof) dokáže generovat profily a vizualizovat je jako plamenné grafy pomocí standardní sady nástrojů. O jejich použití a průvodci nastavením budu mluvit dále v článku.

Provedení, pozorování, rozbor.

Udělejme experiment. Budeme provádět, pozorovat a analyzovat, dokud nebudeme s výkonem spokojeni. Zvolme libovolně nízkou hodnotu zatížení, kterou použijeme pro získání výsledků prvních pozorování. V každém následujícím kroku zvýšíme zátěž s určitým měřítkovým faktorem, zvoleným s určitou obměnou. Každý běh zátěžového testování se provádí s upraveným počtem požadavků: make load-test LOAD_TEST_RATE=X.

50 požadavků za sekundu

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

Věnujte pozornost dvěma horním grafům. Vlevo nahoře je vidět, že naše aplikace zpracovává 50 požadavků za sekundu (myslí) a vpravo nahoře je zobrazena doba trvání každého požadavku. Oba parametry nám pomáhají dívat se a analyzovat, zda jsme v rámci našich výkonnostních hranic, či nikoli. Červená čára na grafu Latence požadavku HTTP ukazuje SLO na 60 ms. Čára ukazuje, že jsme hluboko pod naší maximální dobou odezvy.

Podívejme se na nákladovou stránku:

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

Toto číslo můžeme ještě zlepšit.

500 požadavků za sekundu

Zajímavější věci se začnou dít, když zatížení dosáhne 500 požadavků za sekundu:

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

Opět v levém horním grafu vidíte, že aplikace zaznamenává běžnou zátěž. Pokud tomu tak není, je problém na serveru, na kterém je aplikace spuštěna. Graf latence odezvy je umístěn vpravo nahoře a ukazuje, že 500 požadavků za sekundu mělo za následek zpoždění odezvy 25–40 ms. 99. percentil stále dobře zapadá do výše zvoleného 60ms SLO.

Z hlediska nákladů:

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

Vše se dá ještě vylepšit.

1000 požadavků za sekundu

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

Skvělý start! Aplikace ukazuje, že zpracovala 1000 požadavků za sekundu, ale limit latence byl porušen SLO. To je vidět na řádku p99 v grafu vpravo nahoře. Navzdory skutečnosti, že linka p100 je mnohem vyšší, skutečné zpoždění je vyšší než maximum 60 ms. Pojďme se vrhnout na profilování, abychom zjistili, co aplikace vlastně dělá.

Profilování

Pro profilování nastavíme zatížení na 1000 požadavků za sekundu a poté použijeme pprof k zachycení dat, abyste zjistili, kde aplikace tráví čas CPU. To lze provést aktivací koncového bodu HTTP pprofa poté při zatížení uložte výsledky pomocí curl:

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

Výsledky lze zobrazit takto:

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

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

Graf ukazuje, kde a kolik aplikace tráví čas CPU. Z popisu od Brendan Gregg:

Osa X je populace profilu zásobníku seřazená abecedně (toto není čas), osa Y ukazuje hloubku zásobníku, počítáno od nuly nahoře [nahoře]. Každý obdélník je rámeček. Čím širší je rám, tím častěji je přítomen v hromadách. To, co je nahoře, běží na CPU a to, co je níže, jsou podřízené prvky. Barvy obvykle nic neznamenají, ale jsou jednoduše vybrány náhodně, aby odlišily rámečky.

Analýza - hypotéza

Při ladění se zaměříme na hledání ztraceného času CPU. Budeme hledat největší zdroje zbytečných výdajů a odstraníme je. Vzhledem k tomu, že profilování velmi přesně odhaluje, kde přesně aplikace tráví svůj procesorový čas, možná to budete muset udělat několikrát a také budete muset změnit zdrojový kód aplikace, znovu spustit testy a uvidíte, že se výkon blíží cíli.

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 do programu, rodič všech ostatních volání (jinými slovy, všechna ostatní volání jej budou mít ve svém zásobníku). Další řádek je již jiný:

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

Pokud najedete kurzorem na název funkce v grafu, zobrazí se celkový čas, kdy byla v zásobníku během ladění. Funkce HTTPServe tam byla 65 % času, ostatní runtime funkce runtime.mcall, mstart и gc, zabral zbytek času. Zajímavost: 5 % z celkového času je věnováno DNS dotazům:

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

Adresy, které program hledá, patří do Postgresql. Klikněte na FindByAge:

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

Zajímavé je, že program ukazuje, že v zásadě existují tři hlavní zdroje, které přidávají zpoždění: otevírání a zavírání připojení, vyžádání dat a připojení k databázi. Graf ukazuje, že požadavky DNS, otevírání a zavírání spojení zabírají asi 13 % z celkové doby provádění.

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

Nastavení aplikace - experiment

Aktualizujeme zdrojový kód, snažíme se u každého požadavku odstranit připojení k Postgresql. První možností je použít přípojný bazén na aplikační úrovni. V tomto experimentu jsme pojďme to nastavit sdružování připojení pomocí ovladače sql for go:

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

if err != nil {
   return nil, err
}

Provedení, pozorování, analýza

Po restartování testu s 1000 požadavky za sekundu je jasné, že úrovně latence p99 se vrátily do normálu se SLO 60 ms!

kolik to stojí?

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

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

2000 požadavků za sekundu

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

Zdvojnásobení zátěže ukazuje to samé, levý horní graf ukazuje, že aplikace zvládá zpracovat 2000 požadavků za vteřinu, p100 je nižší než 60ms, p99 vyhovuje SLO.

Z hlediska nákladů:

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

3000 požadavků za sekundu

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

Zde aplikace dokáže zpracovat 3000 požadavků s latencí p99 menší než 60 ms. SLO není porušeno a náklady jsou akceptovány následovně:

10000 3000 požadavků za sekundu / na 4 1 požadavků na server = XNUMX servery + XNUMX (autor zaokrouhlil nahoru, Cca. překladatel)

Zkusme další kolo analýzy.

Analýza - hypotéza

Shromažďujeme a zobrazujeme výsledky ladění aplikace rychlostí 3000 požadavků za sekundu:

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

Stále je 6 % času stráveno navazováním spojení. Nastavení fondu zlepšilo výkon, ale stále můžete vidět, že aplikace nadále pracuje na vytváření nových připojení k databázi.

Hypotéza: Připojení, navzdory přítomnosti fondu, jsou stále zrušena a vyčištěna, takže je aplikace musí resetovat. Nastavení počtu čekajících připojení na velikost fondu by mělo pomoci s latencí tím, že minimalizuje čas, který aplikace stráví vytvářením připojení..

Nastavení aplikace - experiment

Pokus o instalaci MaxIdleConns rovná velikosti bazénu (také popsáno zde):

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

Provedení, pozorování, analýza

3000 požadavků za sekundu

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

p99 je méně než 60 ms s výrazně menším p100!

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

Kontrola plamene ukazuje, že spojení již není patrné! Pojďme to zkontrolovat podrobněji pg(*conn).query - také si nevšimneme navazování spojení zde.

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

Závěr

Analýza výkonu je zásadní pro pochopení toho, že jsou splněna očekávání zákazníků a nefunkční požadavky. Analýza porovnáním pozorování s očekáváním zákazníků může pomoci určit, co je přijatelné a co ne. Go poskytuje výkonné nástroje zabudované do standardní knihovny, díky kterým je analýza jednoduchá a přístupná.

Zdroj: www.habr.com

Přidat komentář