SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Analiza in nastavitev zmogljivosti je močno orodje za preverjanje skladnosti zmogljivosti za stranke.

Analizo uspešnosti je mogoče uporabiti za preverjanje ozkih grl v programu z uporabo znanstvenega pristopa k testiranju poskusov prilagajanja. Ta članek opredeljuje splošen pristop k analizi zmogljivosti in prilagajanju, pri čemer kot primer uporablja spletni strežnik Go.

Go je tukaj še posebej dober, ker ima orodja za profiliranje pprof v standardni knjižnici.

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Strategija

Ustvarimo seznam povzetkov za našo strukturno analizo. Namesto sprememb na podlagi intuicije ali ugibanja bomo poskušali uporabiti nekatere podatke za sprejemanje odločitev. Da bi to naredili, bomo naredili to:

  • Določimo meje optimizacije (zahteve);
  • Izračunamo transakcijsko obremenitev sistema;
  • Izvedemo test (ustvarimo podatke);
  • Opazujemo;
  • Analiziramo – ali so vse zahteve izpolnjene?
  • Znanstveno postavimo, postavimo hipotezo;
  • Izvajamo poskus, da preverimo to hipotezo.

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Preprosta arhitektura strežnika HTTP

Za ta članek bomo uporabili majhen strežnik HTTP v Golangu. Vso kodo iz tega članka lahko najdete tukaj.

Aplikacija, ki se analizira, je strežnik HTTP, ki za vsako zahtevo vpraša Postgresql. Poleg tega so na voljo Prometheus, node_exporter in Grafana za zbiranje in prikazovanje aplikacijskih in sistemskih meritev.

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Za poenostavitev menimo, da sta za vodoravno skaliranje (in poenostavitev izračunov) vsaka storitev in baza podatkov razporejeni skupaj:

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Določitev ciljev

Na tem koraku se odločimo za cilj. Kaj poskušamo analizirati? Kako vemo, kdaj je čas za konec? V tem članku si bomo predstavljali, da imamo stranke in da bo naša storitev obdelala 10 zahtevkov na sekundo.

В Google SRE knjiga Podrobno so obravnavane metode izbire in modeliranja. Naredimo enako in zgradimo modele:

  • Zakasnitev: 99 % zahtevkov mora biti izpolnjenih v manj kot 60 ms;
  • Stroški: Storitev bi morala porabiti najmanjšo količino denarja, za katero menimo, da je razumno možna. Da bi to naredili, povečamo prepustnost;
  • Načrtovanje zmogljivosti: zahteva razumevanje in dokumentiranje, koliko primerkov aplikacije bo treba zagnati, vključno s celotno funkcionalnostjo skaliranja, in koliko primerkov bo potrebnih za izpolnitev začetnih zahtev glede obremenitve in oskrbe. redundanca n+1.

Zakasnitev lahko zahteva optimizacijo poleg analize, vendar je prepustnost očitno treba analizirati. Pri uporabi postopka SRE SLO zahtevo za zamudo poda stranka ali podjetje, ki ga zastopa lastnik izdelka. In naš servis bo to obveznost izpolnil že od samega začetka brez nastavitev!

Nastavitev testnega okolja

S pomočjo testnega okolja bomo lahko izmerjeno obremenili naš sistem. Za analizo bodo generirani podatki o delovanju spletne storitve.

Transakcijska obremenitev

To okolje uporablja Živeti za ustvarjanje stopnje zahtev HTTP po meri, dokler se ne ustavi:

$ 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

Opazovanje

Transakcijska obremenitev bo uporabljena med izvajanjem. Poleg meritev aplikacije (število zahtev, zakasnitev odziva) in operacijskega sistema (pomnilnik, CPE, IOPS) se bo izvajalo profiliranje aplikacije, da bi ugotovili, kje ima težave in kako se porablja čas procesorja.

Profiliranje

Profiliranje je vrsta merjenja, ki vam omogoča, da vidite, kam gre CPE čas, ko se aplikacija izvaja. Omogoča vam natančno določitev, kje in koliko procesorskega časa se porabi:

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Te podatke je mogoče uporabiti med analizo za pridobitev vpogleda v izgubljeni čas procesorja in opravljeno nepotrebno delo. Go (pprof) lahko ustvari profile in jih vizualizira kot plamenske grafe z uporabo standardnega nabora orodij. O njihovi uporabi in vodniku za nastavitev bom govoril pozneje v članku.

Izvedba, opazovanje, analiza.

Izvedimo poskus. Izvajali bomo, opazovali in analizirali, dokler ne bomo z izvedbo zadovoljni. Izberimo poljubno nizko vrednost obremenitve, da jo uporabimo za pridobitev rezultatov prvih opazovanj. Pri vsakem naslednjem koraku bomo povečali obremenitev z določenim skalirnim faktorjem, izbranim z nekaj variacijami. Vsak zagon obremenitvenega testiranja se izvede s prilagojenim številom zahtev: make load-test LOAD_TEST_RATE=X.

50 zahtevkov na sekundo

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Bodite pozorni na zgornja dva grafa. Levo zgoraj prikazuje, da naša aplikacija obdela 50 zahtevkov na sekundo (misli), desno zgoraj pa prikazuje trajanje posamezne zahteve. Oba parametra nam pomagata videti in analizirati, ali smo znotraj svojih meja uspešnosti ali ne. Rdeča črta na grafu Zakasnitev zahteve HTTP prikazuje SLO pri 60ms. Vrstica kaže, da smo precej pod našim največjim odzivnim časom.

Poglejmo stroškovno stran:

10000 zahtev na sekundo / 50 zahtev na strežnik = 200 strežnikov + 1

To številko lahko še izboljšamo.

500 zahtevkov na sekundo

Bolj zanimive stvari se začnejo dogajati, ko obremenitev doseže 500 zahtev na sekundo:

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Spet v zgornjem levem grafu vidite, da aplikacija beleži normalno obremenitev. Če temu ni tako, je težava na strežniku, na katerem se izvaja aplikacija. Graf zakasnitve odziva se nahaja zgoraj desno in prikazuje, da je 500 zahtev na sekundo povzročilo zakasnitev odgovora 25–40 ms. 99. percentil se še vedno lepo ujema z zgoraj izbrano 60ms SLO.

Glede stroškov:

10000 zahtev na sekundo / 500 zahtev na strežnik = 20 strežnikov + 1

Vse se da še izboljšati.

1000 zahtevkov na sekundo

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Odličen začetek! Aplikacija kaže, da je obdelala 1000 zahtevkov na sekundo, vendar je omejitev latence prekoračila SLO. To lahko vidite v vrstici p99 v zgornjem desnem grafu. Kljub dejstvu, da je linija p100 precej višja, so dejanske zakasnitve višje od maksimalnih 60 ms. Poglobimo se v profiliranje, da ugotovimo, kaj aplikacija dejansko počne.

Profiliranje

Za profiliranje nastavimo obremenitev na 1000 zahtev na sekundo, nato uporabimo pprof za zajemanje podatkov, da bi ugotovili, kje aplikacija porablja čas procesorja. To lahko storite tako, da aktivirate končno točko HTTP pprof, nato pa pod obremenitvijo shranite rezultate z uporabo curl:

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

Rezultate lahko prikažete takole:

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

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Graf prikazuje, kje in koliko aplikacija porabi procesorskega časa. Iz opisa iz Brendan Gregg:

Os X je populacija profila sklada, razvrščena po abecedi (to ni čas), os Y prikazuje globino sklada, šteto od nič na [zgoraj]. Vsak pravokotnik je okvir sklada. Širši kot je okvir, pogosteje je prisoten v nizih. Tisto, kar je na vrhu, deluje na CPE, tisto, kar je spodaj, pa so podrejeni elementi. Barve običajno ne pomenijo ničesar, ampak so preprosto izbrane naključno za razlikovanje okvirjev.

Analiza - hipoteza

Za uglaševanje se bomo osredotočili na iskanje zapravljenega časa procesorja. Iskali bomo največje vire nekoristne porabe in jih odstranili. No, glede na to, da profiliranje zelo natančno razkrije, kje točno aplikacija porabi svoj procesorski čas, ga boste morda morali narediti večkrat, poleg tega pa boste morali spremeniti izvorno kodo aplikacije, znova zagnati teste in preveriti, ali se zmogljivost približuje cilju.

Po priporočilih Brendana Gregga bomo grafikon prebrali od zgoraj navzdol. Vsaka vrstica prikazuje okvir sklada (klic funkcije). Prva vrstica je vstopna točka v program, nadrejena za vse druge klice (z drugimi besedami, vsi drugi klici jo bodo imeli na svojem skladu). Naslednja vrstica je že drugačna:

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Če kazalec premaknete nad ime funkcije na grafu, bo prikazan skupni čas, ko je bila funkcija na skladu med odpravljanjem napak. Funkcija HTTPServe je bila tam 65 % časa, druge funkcije izvajalnega okolja runtime.mcall, mstart и gc, vzel preostali čas. Zanimivost: 5 % celotnega časa porabimo za poizvedbe DNS:

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Naslovi, ki jih program išče, pripadajo Postgresqlu. Kliknite na FindByAge:

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Zanimivo je, da program kaže, da načeloma obstajajo trije glavni viri, ki dodajajo zamude: odpiranje in zapiranje povezav, zahtevanje podatkov in povezovanje z bazo podatkov. Graf prikazuje, da zahteve DNS, odpiranje in zapiranje povezav zavzamejo približno 13 % celotnega časa izvajanja.

Hipoteza: Ponovna uporaba povezav z združevanjem bi morala skrajšati čas posamezne zahteve HTTP, kar bi omogočilo večjo prepustnost in manjšo zakasnitev.

Nastavitev aplikacije – poskus

Posodabljamo izvorno kodo, poskušamo odstraniti povezavo s Postgresql za vsako zahtevo. Prva možnost je uporaba povezovalni bazen na ravni aplikacije. V tem poskusu smo postavimo ga zbiranje povezav z gonilnikom sql za go:

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

if err != nil {
   return nil, err
}

Izvedba, opazovanje, analiza

Po ponovnem zagonu testa s 1000 zahtevami na sekundo je jasno, da so se stopnje zakasnitve p99 vrnile v normalno stanje s SLO 60 ms!

Kakšna je cena?

10000 zahtev na sekundo / 1000 zahtev na strežnik = 10 strežnikov + 1

Naredimo to še bolje!

2000 zahtevkov na sekundo

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Podvojitev obremenitve pokaže isto, zgornji levi graf kaže, da aplikacija uspe obdelati 2000 zahtevkov na sekundo, p100 je nižji od 60ms, p99 zadovolji SLO.

Glede stroškov:

10000 zahtev na sekundo / 2000 zahtev na strežnik = 5 strežnikov + 1

3000 zahtevkov na sekundo

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Tu lahko aplikacija obdela 3000 zahtevkov z zakasnitvijo p99 manj kot 60 ms. SLO ni kršen, stroški pa so sprejeti na naslednji način:

10000 zahtev na sekundo / na 3000 zahtev na strežnik = 4 strežniki + 1 (avtor je zaokrožil, pribl. prevajalec)

Poskusimo še en krog analize.

Analiza - hipoteza

Zbiramo in prikazujemo rezultate odpravljanja napak aplikacije pri 3000 zahtevah na sekundo:

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Še vedno pa 6 % časa porabimo za vzpostavljanje povezav. Nastavitev bazena je izboljšala zmogljivost, vendar lahko še vedno vidite, da aplikacija še naprej ustvarja nove povezave z bazo podatkov.

Hipoteza: Povezave so kljub prisotnosti bazena še vedno opuščene in očiščene, zato jih mora aplikacija ponastaviti. Nastavitev števila čakajočih povezav na velikost bazena bi morala pomagati pri zakasnitvi, saj zmanjša čas, ki ga aplikacija porabi za ustvarjanje povezave.

Nastavitev aplikacije – poskus

Poskušam namestiti MaxIdleConns enaka velikosti bazena (opisano tudi tukaj):

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

Izvedba, opazovanje, analiza

3000 zahtevkov na sekundo

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

p99 je manj kot 60 ms z bistveno manjšim p100!

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Preverjanje grafa plamena pokaže, da povezava ni več opazna! Preverimo podrobneje pg(*conn).query — prav tako ne opazimo povezave, ki se vzpostavlja tukaj.

SRE: Analiza uspešnosti. Metoda konfiguracije z uporabo preprostega spletnega strežnika v Go

Zaključek

Analiza uspešnosti je ključnega pomena za razumevanje, ali so pričakovanja strank in nefunkcionalne zahteve izpolnjene. Analiza s primerjavo opažanj s pričakovanji strank lahko pomaga ugotoviti, kaj je sprejemljivo in kaj ne. Go ponuja zmogljiva orodja, vgrajena v standardno knjižnico, ki naredijo analizo preprosto in dostopno.

Vir: www.habr.com

Dodaj komentar