SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Analiza dhe akordimi i performancës është një mjet i fuqishëm për verifikimin e pajtueshmërisë së performancës për klientët.

Analiza e performancës mund të përdoret për të kontrolluar pengesat në një program duke aplikuar një qasje shkencore për testimin e eksperimenteve të akordimit. Ky artikull përcakton një qasje të përgjithshme për analizën dhe akordimin e performancës, duke përdorur një server në internet Go si shembull.

Go është veçanërisht e mirë këtu sepse ka mjete profilizimi pprof në bibliotekën standarde.

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

strategji

Le të krijojmë një listë përmbledhëse për analizën tonë strukturore. Ne do të përpiqemi të përdorim disa të dhëna për të marrë vendime në vend që të bëjmë ndryshime bazuar në intuitë ose hamendje. Për ta bërë këtë ne do të bëjmë këtë:

  • Ne përcaktojmë kufijtë e optimizimit (kërkesat);
  • Ne llogarisim ngarkesën e transaksionit për sistemin;
  • Ne kryejmë testin (krijojmë të dhëna);
  • Ne vëzhgojmë;
  • Ne analizojmë - a janë plotësuar të gjitha kërkesat?
  • E kemi ngritur shkencërisht, bëjmë një hipotezë;
  • Ne kryejmë një eksperiment për të testuar këtë hipotezë.

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Arkitekturë e thjeshtë e serverit HTTP

Për këtë artikull ne do të përdorim një server të vogël HTTP në Golang. I gjithë kodi nga ky artikull mund të gjendet këtu.

Aplikacioni që analizohet është një server HTTP që anketon Postgresql për çdo kërkesë. Për më tepër, ka Prometheus, node_exporter dhe Grafana për mbledhjen dhe shfaqjen e matjeve të aplikacioneve dhe sistemit.

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Për të thjeshtuar, ne konsiderojmë se për shkallëzimin horizontal (dhe thjeshtimin e llogaritjeve) çdo shërbim dhe bazë të dhënash vendosen së bashku:

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Përcaktimi i qëllimeve

Në këtë hap, ne vendosim për qëllimin. Çfarë po përpiqemi të analizojmë? Si e dimë se kur është koha për të përfunduar? Në këtë artikull, ne do të imagjinojmë se kemi klientë dhe se shërbimi ynë do të përpunojë 10 kërkesa në sekondë.

В Libri Google SRE Metodat e përzgjedhjes dhe modelimit diskutohen në detaje. Le të bëjmë të njëjtën gjë dhe të ndërtojmë modele:

  • Vonesa: 99% e kërkesave duhet të plotësohen në më pak se 60ms;
  • Kostoja: Shërbimi duhet të konsumojë sasinë minimale të parave që ne mendojmë se është e mundur në mënyrë të arsyeshme. Për ta bërë këtë, ne maksimizojmë xhiros;
  • Planifikimi i kapacitetit: Kërkon të kuptuarit dhe dokumentimin se sa instanca të aplikacionit do të duhet të ekzekutohen, duke përfshirë funksionalitetin e përgjithshëm të shkallëzimit dhe sa shembuj do të nevojiten për të përmbushur kërkesat fillestare të ngarkesës dhe furnizimit tepricë n+1.

Vonesa mund të kërkojë optimizim përveç analizës, por xhiroja duhet të analizohet qartë. Kur përdorni procesin SRE SLO, kërkesa për vonesë vjen nga klienti ose biznesi, i përfaqësuar nga pronari i produktit. Dhe shërbimi ynë do ta përmbushë këtë detyrim që në fillim pa asnjë cilësim!

Vendosja e një mjedisi testimi

Me ndihmën e një mjedisi testimi, ne do të jemi në gjendje të vendosim një ngarkesë të matur në sistemin tonë. Për analizë, do të gjenerohen të dhëna për performancën e shërbimit të internetit.

Ngarkesa e transaksionit

Ky mjedis përdor Vegeta për të krijuar një normë të personalizuar të kërkesës HTTP derisa të ndalet:

$ 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

shikuar

Ngarkesa transaksionale do të aplikohet në kohën e ekzekutimit. Përveç matjeve të aplikacionit (numri i kërkesave, vonesa e përgjigjes) dhe sistemi operativ (memoria, CPU, IOPS), do të kryhet profilizimi i aplikacionit për të kuptuar se ku ka probleme dhe si harxhohet koha e CPU-së.

Profilizimi

Profilizimi është një lloj matjeje që ju lejon të shihni se ku shkon koha e CPU-së kur një aplikacion po funksionon. Kjo ju lejon të përcaktoni saktësisht se ku dhe sa kohë është shpenzuar procesori:

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Këto të dhëna mund të përdoren gjatë analizës për të fituar njohuri për kohën e humbur të CPU-së dhe punën e panevojshme që po kryhet. Go (pprof) mund të gjenerojë profile dhe t'i vizualizojë ato si grafikë flakë duke përdorur një grup standard mjetesh. Unë do të flas për përdorimin e tyre dhe udhëzuesin e konfigurimit më vonë në artikull.

Ekzekutimi, vëzhgimi, analiza.

Le të bëjmë një eksperiment. Ne do të performojmë, vëzhgojmë dhe analizojmë derisa të jemi të kënaqur me performancën. Le të zgjedhim një vlerë arbitrare të ulët të ngarkesës për ta zbatuar atë për të marrë rezultatet e vëzhgimeve të para. Në çdo hap pasues do të rrisim ngarkesën me një faktor të caktuar shkallëzimi, të zgjedhur me disa ndryshime. Çdo ekzekutim i testimit të ngarkesës kryhet me numrin e kërkesave të rregulluara: make load-test LOAD_TEST_RATE=X.

50 kërkesa në sekondë

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Kushtojini vëmendje dy grafikëve të lartë. Pjesa e sipërme majtas tregon se aplikacioni ynë përpunon 50 kërkesa në sekondë (mendon) dhe lart djathtas tregon kohëzgjatjen e secilës kërkesë. Të dy parametrat na ndihmojnë të shikojmë dhe analizojmë nëse jemi brenda kufijve tanë të performancës apo jo. Vija e kuqe në grafik Vonesa e kërkesës HTTP tregon SLO në 60ms. Linja tregon se jemi shumë nën kohën tonë maksimale të përgjigjes.

Le të shohim anën e kostos:

10000 kërkesa për sekondë / 50 kërkesa për server = 200 serverë + 1

Ne ende mund ta përmirësojmë këtë shifër.

500 kërkesa në sekondë

Gjëra më interesante fillojnë të ndodhin kur ngarkesa arrin në 500 kërkesa në sekondë:

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Përsëri, në grafikun e sipërm majtas mund të shihni se aplikacioni po regjistron ngarkesën normale. Nëse nuk është kështu, ka një problem në serverin në të cilin po ekzekutohet aplikacioni. Grafiku i vonesës së përgjigjes ndodhet lart djathtas, duke treguar se 500 kërkesa në sekondë rezultuan në një vonesë përgjigjeje prej 25-40 ms. Përqindja e 99-të ende përshtatet mirë në SLO 60ms të zgjedhur më sipër.

Për sa i përket kostos:

10000 kërkesa për sekondë / 500 kërkesa për server = 20 serverë + 1

Gjithçka ende mund të përmirësohet.

1000 kërkesa në sekondë

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Nisja e shkëlqyer! Aplikacioni tregon se ka përpunuar 1000 kërkesa në sekondë, por kufiri i vonesës është shkelur nga SLO. Kjo mund të shihet në rreshtin p99 në grafikun e sipërm djathtas. Pavarësisht se linja p100 është shumë më e lartë, vonesat aktuale janë më të larta se maksimumi 60ms. Le të zhytemi në profilizimin për të zbuluar se çfarë bën në të vërtetë aplikacioni.

Profilizimi

Për profilizimin, vendosëm ngarkesën në 1000 kërkesa për sekondë, më pas përdorim pprof për të kapur të dhëna për të zbuluar se ku po e shpenzon aplikacioni kohën e CPU-së. Kjo mund të bëhet duke aktivizuar pikën përfundimtare HTTP pprof, dhe më pas, nën ngarkesë, ruani rezultatet duke përdorur curl:

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

Rezultatet mund të shfaqen si kjo:

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

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Grafiku tregon se ku dhe sa e shpenzon aplikacioni kohën e CPU-së. Nga përshkrimi nga Brendan Gregg:

Boshti X është popullata e profilit të pirgut, e renditur sipas alfabetit (kjo nuk është koha), boshti Y tregon thellësinë e pirgut, duke numëruar nga zero në [lart]. Çdo drejtkëndësh është një kornizë pirg. Sa më e gjerë të jetë korniza, aq më shpesh është e pranishme në pirgje. Ajo që është në krye funksionon në CPU, dhe ajo që është më poshtë janë elementët fëmijë. Ngjyrat zakonisht nuk do të thotë asgjë, por thjesht zgjidhen rastësisht për të dalluar kornizat.

Analizë – hipotezë

Për akordim, ne do të përqendrohemi në përpjekjen për të gjetur kohën e humbur të CPU-së. Ne do të kërkojmë burimet më të mëdha të shpenzimeve të padobishme dhe do t'i heqim ato. Epo, duke pasur parasysh se profilizimi zbulon me shumë saktësi se ku saktësisht aplikacioni po e kalon kohën e tij të procesorit, mund t'ju duhet ta bëni atë disa herë, dhe gjithashtu do t'ju duhet të ndryshoni kodin burimor të aplikacionit, të riktheni testet dhe të shihni që performanca i afrohet objektivit.

Duke ndjekur rekomandimet e Brendan Gregg, ne do të lexojmë grafikun nga lart poshtë. Çdo rresht shfaq një kornizë stek (thirrje funksioni). Rreshti i parë është pika e hyrjes në program, prindi i të gjitha thirrjeve të tjera (me fjalë të tjera, të gjitha thirrjet e tjera do ta kenë atë në stivën e tyre). Rreshti tjetër është tashmë i ndryshëm:

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Nëse e vendosni kursorin mbi emrin e një funksioni në grafik, do të shfaqet koha totale që ka qenë në pirg gjatë korrigjimit. Funksioni HTTPServe ishte aty 65% ​​të kohës, funksione të tjera të kohës së ekzekutimit runtime.mcall, mstart и gc, mori pjesën tjetër të kohës. Fakt argëtues: 5% e kohës totale shpenzohet në pyetjet DNS:

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Adresat që kërkon programi i përkasin Postgresql. Klikoni mbi FindByAge:

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Interesante, programi tregon se, në parim, ekzistojnë tre burime kryesore që shtojnë vonesat: hapja dhe mbyllja e lidhjeve, kërkimi i të dhënave dhe lidhja me bazën e të dhënave. Grafiku tregon se kërkesat DNS, hapja dhe mbyllja e lidhjeve zënë rreth 13% të kohës totale të ekzekutimit.

Hipoteza: Ripërdorimi i lidhjeve duke përdorur bashkimin duhet të zvogëlojë kohën e një kërkese të vetme HTTP, duke lejuar qarkullim më të lartë dhe vonesë më të ulët.

Vendosja e aplikacionit - eksperiment

Ne përditësojmë kodin burimor, përpiqemi të heqim lidhjen me Postgresql për çdo kërkesë. Opsioni i parë është përdorimi pishina e lidhjes në nivelin e aplikimit. Në këtë eksperiment ne le ta vendosim bashkimi i lidhjes duke përdorur drejtuesin sql për go:

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

if err != nil {
   return nil, err
}

Ekzekutimi, vëzhgimi, analiza

Pas rifillimit të testit me 1000 kërkesa në sekondë, është e qartë se nivelet e vonesës së p99 janë kthyer në normale me një SLO prej 60ms!

sa kushton?

10000 kërkesa për sekondë / 1000 kërkesa për server = 10 serverë + 1

Le ta bëjmë edhe më mirë!

2000 kërkesa në sekondë

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Dyfishimi i ngarkesës tregon të njëjtën gjë, grafiku i sipërm majtas tregon se aplikacioni arrin të përpunojë 2000 kërkesa në sekondë, p100 është më e ulët se 60ms, p99 kënaq SLO.

Për sa i përket kostos:

10000 kërkesa për sekondë / 2000 kërkesa për server = 5 serverë + 1

3000 kërkesa në sekondë

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Këtu aplikacioni mund të përpunojë 3000 kërkesa me një vonesë p99 më pak se 60ms. SLO nuk është shkelur, dhe kostoja pranohet si më poshtë:

10000 kërkesa për sekondë / për 3000 kërkesa për server = 4 server + 1 (autori ka përmbledhur, përafërsisht. përkthyes)

Le të provojmë një raund tjetër analize.

Analizë – hipotezë

Ne mbledhim dhe shfaqim rezultatet e korrigjimit të aplikacionit me 3000 kërkesa në sekondë:

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Ende 6% e kohës shpenzohet për vendosjen e lidhjeve. Konfigurimi i grupit ka përmirësuar performancën, por prapë mund të shihni se aplikacioni vazhdon të punojë për krijimin e lidhjeve të reja me bazën e të dhënave.

Hipoteza: Lidhjet, pavarësisht nga prania e një pishinë, ende janë hequr dhe pastruar, kështu që aplikacioni duhet t'i rivendosë ato. Vendosja e numrit të lidhjeve në pritje në madhësinë e pishinës duhet të ndihmojë me vonesën duke minimizuar kohën që aplikacioni shpenzon duke krijuar një lidhje.

Vendosja e aplikacionit - eksperiment

Duke u përpjekur për të instaluar MaxIdleConns e barabartë me madhësinë e pishinës (e përshkruar gjithashtu këtu):

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

Ekzekutimi, vëzhgimi, analiza

3000 kërkesa në sekondë

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

p99 është më pak se 60ms me shumë më pak p100!

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Kontrollimi i grafikut të flakës tregon se lidhja nuk është më e dukshme! Le të kontrollojmë më në detaje pg(*conn).query — gjithashtu nuk e vërejmë lidhjen që po krijohet këtu.

SRE: Analiza e Performancës. Metoda e konfigurimit duke përdorur një server të thjeshtë në internet në Go

Përfundim

Analiza e performancës është kritike për të kuptuar se pritshmëritë e klientëve dhe kërkesat jofunksionale janë duke u përmbushur. Analiza duke krahasuar vëzhgimet me pritjet e klientëve mund të ndihmojë në përcaktimin se çfarë është e pranueshme dhe çfarë jo. Go ofron mjete të fuqishme të integruara në bibliotekën standarde që e bëjnë analizën të thjeshtë dhe të arritshme.

Burimi: www.habr.com

Shto një koment