SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Analiza i podešavanje performansi je moćan alat za provjeru usklađenosti performansi za klijente.

Analiza performansi se može koristiti za provjeru uskih grla u programu primjenom naučnog pristupa testiranju eksperimenata podešavanja. Ovaj članak definira opći pristup analizi i podešavanju performansi, koristeći Go web server kao primjer.

Go je ovdje posebno dobar jer ima alate za profiliranje pprof u standardnoj biblioteci.

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Strategija

Kreirajmo sažetu listu za našu strukturnu analizu. Pokušat ćemo koristiti neke podatke za donošenje odluka umjesto da unosimo promjene na osnovu intuicije ili nagađanja. Da bismo to uradili, uradićemo sledeće:

  • Određujemo granice optimizacije (zahtjeve);
  • Izračunavamo opterećenje transakcije za sistem;
  • Vršimo test (kreiramo podatke);
  • Mi posmatramo;
  • Analiziramo - da li su ispunjeni svi zahtjevi?
  • Mi to postavljamo naučno, postavljamo hipotezu;
  • Izvodimo eksperiment kako bismo provjerili ovu hipotezu.

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Jednostavna arhitektura HTTP servera

Za ovaj članak ćemo koristiti mali HTTP server u Golangu. Sav kod iz ovog članka možete pronaći ovdje.

Aplikacija koja se analizira je HTTP server koji ispituje Postgresql za svaki zahtjev. Dodatno, tu su Prometheus, node_exporter i Grafana za prikupljanje i prikaz aplikacijskih i sistemskih metrika.

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Da pojednostavimo, smatramo da se za horizontalno skaliranje (i pojednostavljivanje izračunavanja) svaka usluga i baza podataka postavljaju zajedno:

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Definisanje ciljeva

Na ovom koraku odlučujemo se o cilju. Šta pokušavamo analizirati? Kako da znamo kada je vrijeme za kraj? U ovom članku ćemo zamisliti da imamo klijente i da naš servis obrađuje 10 zahtjeva u sekundi.

В Google SRE knjiga Detaljno su razmotrene metode selekcije i modeliranja. Uradimo isto i napravimo modele:

  • Latencija: 99% zahtjeva treba biti završeno za manje od 60ms;
  • Trošak: Usluga bi trebala potrošiti minimalnu količinu novca za koju mislimo da je razumno moguća. Da bismo to učinili, maksimiziramo propusnost;
  • Planiranje kapaciteta: Zahtijeva razumijevanje i dokumentiranje koliko će instanci aplikacije biti potrebno pokrenuti, uključujući ukupnu funkcionalnost skaliranja i koliko će instanci biti potrebno da bi se ispunili zahtjevi za početno opterećenje i obezbjeđivanje redundancija n+1.

Latencija može zahtijevati optimizaciju pored analize, ali propusnost jasno mora biti analizirana. Kada se koristi SRE SLO proces, zahtjev za odgodom dolazi od kupca ili tvrtke, koju predstavlja vlasnik proizvoda. A naš servis će tu obavezu ispuniti od samog početka bez ikakvih podešavanja!

Postavljanje testnog okruženja

Uz pomoć okruženja za testiranje, moći ćemo izmjereno opterećenje na naš sistem. Za analizu će se generirati podaci o performansama web servisa.

Opterećenje transakcije

Ovo okruženje koristi Vegeta da kreirate prilagođenu stopu HTTP zahtjeva dok se ne zaustavi:

$ 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

Posmatranje

Transakcijsko opterećenje će se primijeniti u vrijeme izvođenja. Pored metrike aplikacije (broj zahtjeva, kašnjenje odgovora) i operativnog sistema (memorija, CPU, IOPS), profiliranje aplikacije će se pokrenuti da bi se razumjelo gdje ima problema i kako se troši CPU vrijeme.

Profilisanje

Profilisanje je vrsta mjerenja koja vam omogućava da vidite kuda ide CPU vrijeme kada se aplikacija pokrene. Omogućava vam da tačno odredite gdje i koliko procesorskog vremena trošite:

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Ovi podaci se mogu koristiti tokom analize kako bi se stekao uvid u izgubljeno CPU vrijeme i nepotreban rad koji se obavlja. Go (pprof) može generirati profile i vizualizirati ih kao grafove plamena koristeći standardni set alata. O njihovoj upotrebi i vodiču za postavljanje govorit ću kasnije u članku.

Izvođenje, posmatranje, analiza.

Hajde da napravimo eksperiment. Radićemo, posmatrati i analizirati sve dok ne budemo zadovoljni učinkom. Odaberimo proizvoljno malu vrijednost opterećenja da bismo je primijenili da bismo dobili rezultate prvih promatranja. U svakom sljedećem koraku povećat ćemo opterećenje s određenim faktorom skaliranja odabranim uz neke varijacije. Svako testiranje opterećenja se izvodi s prilagođenim brojem zahtjeva: make load-test LOAD_TEST_RATE=X.

50 zahtjeva u sekundi

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Obratite pažnju na gornja dva grafikona. Gore lijevo pokazuje da naša aplikacija obrađuje 50 zahtjeva u sekundi (misli), a gore desno prikazuje trajanje svakog zahtjeva. Oba parametra nam pomažu da pogledamo i analiziramo da li smo unutar granica naših performansi ili ne. Crvena linija na grafikonu Kašnjenje HTTP zahtjeva pokazuje SLO na 60ms. Linija pokazuje da smo daleko ispod našeg maksimalnog vremena odziva.

Pogledajmo stranu troškova:

10000 zahtjeva u sekundi / 50 zahtjeva po serveru = 200 servera + 1

Još uvijek možemo poboljšati ovu cifru.

500 zahtjeva u sekundi

Zanimljivije stvari počinju da se dešavaju kada opterećenje dođe do 500 zahteva u sekundi:

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Opet, u gornjem lijevom grafikonu možete vidjeti da aplikacija bilježi normalno opterećenje. Ako to nije slučaj, postoji problem na serveru na kojem se aplikacija izvodi. Grafikon kašnjenja odgovora nalazi se u gornjem desnom uglu i pokazuje da je 500 zahtjeva u sekundi rezultiralo kašnjenjem odgovora od 25-40ms. 99. percentil se još uvijek lijepo uklapa u gore odabrani SLO od 60 ms.

Što se tiče troškova:

10000 zahtjeva u sekundi / 500 zahtjeva po serveru = 20 servera + 1

Sve se još može poboljšati.

1000 zahtjeva u sekundi

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Odlično lansiranje! Aplikacija pokazuje da je obrađivala 1000 zahtjeva u sekundi, ali je ograničenje kašnjenja prekršio SLO. Ovo se može vidjeti u liniji p99 u gornjem desnom grafu. Uprkos činjenici da je linija p100 mnogo veća, stvarna kašnjenja su veća od maksimalnih 60ms. Zaronimo u profilisanje kako bismo saznali šta aplikacija zapravo radi.

Profilisanje

Za profiliranje postavljamo opterećenje na 1000 zahtjeva u sekundi, a zatim koristimo pprof za snimanje podataka kako biste saznali gdje aplikacija troši CPU vrijeme. Ovo se može uraditi aktiviranjem HTTP krajnje tačke pprof, a zatim, pod opterećenjem, sačuvajte rezultate koristeći curl:

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

Rezultati se mogu prikazati ovako:

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

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Grafikon pokazuje gdje i koliko aplikacija troši CPU vremena. Iz opisa iz Brendan Gregg:

X osa je populacija profila steka, sortirana po abecednom redu (ovo nije vrijeme), Y osa prikazuje dubinu steka, računajući od nule na [vrh]. Svaki pravougaonik je stog okvir. Što je okvir širi, to je češće prisutan u naslagama. Ono što je na vrhu radi na CPU-u, a ono što je ispod su podređeni elementi. Boje obično ne znače ništa, već se jednostavno biraju nasumično kako bi se okviri razlikovali.

Analiza - hipoteza

Za podešavanje, fokusirat ćemo se na pokušaj da pronađemo izgubljeno CPU vrijeme. Potražit ćemo najveće izvore beskorisne potrošnje i ukloniti ih. Pa, s obzirom na to da profiliranje vrlo precizno otkriva gdje tačno aplikacija troši svoje procesorsko vrijeme, možda ćete to morati učiniti nekoliko puta, a također ćete morati promijeniti izvorni kod aplikacije, ponovo pokrenuti testove i vidjeti da se performanse približavaju cilju.

Slijedeći preporuke Brendana Gregga, čitat ćemo grafikon od vrha do dna. Svaki red prikazuje okvir steka (poziv funkcije). Prvi red je ulazna tačka u program, roditelj svih ostalih poziva (drugim rečima, svi ostali pozivi će ga imati na svom stogu). Sljedeća linija je već drugačija:

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Ako zadržite pokazivač iznad imena funkcije na grafikonu, prikazat će se ukupno vrijeme koje je bila na steku tokom otklanjanja grešaka. HTTPServe funkcija je bila tu 65% vremena, ostale funkcije vremena izvršavanja runtime.mcall, mstart и gc, zauzimao je ostatak vremena. Zanimljiva činjenica: 5% ukupnog vremena se troši na DNS upite:

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Adrese koje program traži pripadaju Postgresql-u. Kliknite na FindByAge:

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Zanimljivo je da program pokazuje da, u principu, postoje tri glavna izvora koja dodaju kašnjenja: otvaranje i zatvaranje veza, traženje podataka i povezivanje sa bazom podataka. Grafikon pokazuje da DNS zahtjevi, otvaranje i zatvaranje veza zauzimaju oko 13% ukupnog vremena izvršenja.

hipoteza: Ponovna upotreba veza pomoću skupljanja trebala bi smanjiti vrijeme jednog HTTP zahtjeva, omogućavajući veću propusnost i manje kašnjenje.

Postavljanje aplikacije - eksperiment

Ažuriramo izvorni kod, pokušavamo ukloniti vezu sa Postgresql za svaki zahtjev. Prva opcija je korištenje priključni bazen na nivou aplikacije. U ovom eksperimentu mi hajde da ga postavimo spajanje veza pomoću sql drajvera za go:

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

if err != nil {
   return nil, err
}

Izvođenje, posmatranje, analiza

Nakon ponovnog pokretanja testa sa 1000 zahtjeva u sekundi, jasno je da su se nivoi latencije p99 vratili u normalu sa SLO od 60ms!

Koja je cijena?

10000 zahtjeva u sekundi / 1000 zahtjeva po serveru = 10 servera + 1

Uradimo to još bolje!

2000 zahtjeva u sekundi

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Udvostručenje opterećenja pokazuje istu stvar, gornji lijevi grafikon pokazuje da aplikacija uspijeva obraditi 2000 zahtjeva u sekundi, p100 je niže od 60ms, p99 zadovoljava SLO.

Što se tiče troškova:

10000 zahtjeva u sekundi / 2000 zahtjeva po serveru = 5 servera + 1

3000 zahtjeva u sekundi

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Ovdje aplikacija može obraditi 3000 zahtjeva sa p99 latencijom manjim od 60ms. SLO nije prekršen, a trošak se prihvata na sljedeći način:

10000 zahtjeva u sekundi / na 3000 zahtjeva po serveru = 4 servera + 1 (autor je zaokružio, cca. prevodilac)

Pokušajmo sa još jednom rundom analize.

Analiza - hipoteza

Prikupljamo i prikazujemo rezultate otklanjanja grešaka u aplikaciji pri 3000 zahtjeva u sekundi:

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

I dalje se 6% vremena troši na uspostavljanje veze. Postavljanje spremišta je poboljšalo performanse, ali još uvijek možete vidjeti da aplikacija nastavlja raditi na kreiranju novih veza s bazom podataka.

hipoteza: Veze, uprkos prisutnosti bazena, i dalje se ispuštaju i čiste, pa ih aplikacija treba resetirati. Postavljanje broja veza na čekanju na veličinu skupa trebalo bi pomoći u kašnjenju minimiziranjem vremena koje aplikacija troši na kreiranje veze.

Postavljanje aplikacije - eksperiment

Pokušavam instalirati MaxIdleConns jednako veličini bazena (takođe opisano ovdje):

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

Izvođenje, posmatranje, analiza

3000 zahtjeva u sekundi

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

p99 je manje od 60ms sa znatno manje p100!

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

Provjera grafika plamena pokazuje da se veza više ne primjećuje! Hajde da proverimo detaljnije pg(*conn).query — takođe ne primjećujemo da se ovdje uspostavlja veza.

SRE: Analiza učinka. Metoda konfiguracije pomoću jednostavnog web servera u Go

zaključak

Analiza učinka je ključna za razumijevanje da su očekivanja kupaca i nefunkcionalni zahtjevi ispunjeni. Analiza upoređivanjem zapažanja sa očekivanjima kupaca može pomoći da se utvrdi šta je prihvatljivo, a šta nije. Go pruža moćne alate ugrađene u standardnu ​​biblioteku koji analizu čine jednostavnom i pristupačnom.

izvor: www.habr.com

Dodajte komentar