SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Performance Analyse an Tuning ass e mächtegt Tool fir d'Performance Konformitéit fir Clienten z'iwwerpréiwen.

Leeschtungsanalyse kann benotzt ginn fir op Flaschenhals an engem Programm ze kontrolléieren andeems Dir eng wëssenschaftlech Approche applizéiert fir Tuning Experimenter ze testen. Dësen Artikel definéiert eng allgemeng Approche fir d'Performance Analyse an Tuning, mat engem Go Webserver als Beispill.

Go ass besonnesch gutt hei well et Profiling Tools huet pprof an der Standardbibliothéik.

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

D 'Strategie

Loosst eis eng Resumélëscht fir eis strukturell Analyse erstellen. Mir probéieren e puer Donnéeën ze benotzen fir Entscheedungen ze treffen anstatt Ännerungen op Basis vun Intuition oder Guesswork ze maachen. Fir dëst ze maachen wäerte mir dat maachen:

  • Mir bestëmmen d'Optimiséierungsgrenzen (Ufuerderunge);
  • Mir berechnen d'Transaktiounslaascht fir de System;
  • Mir maachen den Test (daten erstellen);
  • Mir beobachten;
  • Mir analyséieren - sinn all Ufuerderunge erfëllt?
  • Mir setzen et wëssenschaftlech op, maachen eng Hypothese;
  • Mir maachen en Experiment fir dës Hypothese ze testen.

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Einfach HTTP Server Architektur

Fir dësen Artikel benotze mir e klenge HTTP-Server am Golang. All Code aus dësem Artikel kann fonnt ginn hei.

D'Applikatioun déi analyséiert gëtt ass en HTTP-Server deen Postgresql fir all Ufro pollt. Zousätzlech gëtt et Prometheus, node_exporter a Grafana fir d'Applikatioun a Systemmetriken ze sammelen an ze weisen.

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Fir ze vereinfachen, betruechte mir datt fir horizontale Skaléieren (a Vereinfachung vun Berechnungen) all Service an Datebank zesummegesat ginn:

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Ziler definéieren

Op dësem Schrëtt entscheede mir iwwer d'Zil. Wat probéieren mir ze analyséieren? Wéi wësse mir wéini et Zäit ass fir opzehalen? An dësem Artikel wäerte mir eis virstellen datt mir Clienten hunn an datt eise Service 10 Ufroe pro Sekonn veraarbecht.

В Google SRE Buch Methode vun der Auswiel a Modelléierung ginn am Detail diskutéiert. Loosst eis datselwecht maachen a Modeller bauen:

  • Latency: 99% vun Ufroe sollen a manner wéi 60ms ofgeschloss ginn;
  • Käschte: De Service soll de Minimum u Sue verbrauchen, déi mir mengen, raisonnabel méiglech ass. Fir dëst ze maachen, maximéiere mir den Duerchgang;
  • Kapazitéitsplanung: Erfuerdert Verständnis an Dokumentatioun wéivill Instanzen vun der Applikatioun musse lafen, inklusiv Gesamtskaléierungsfunktionalitéit, a wéivill Instanzen gebraucht ginn fir initial Belaaschtung a Bestëmmungsufuerderungen z'erreechen Redundanz n+1.

D'Latency kann zousätzlech zur Analyse Optimiséierung erfuerderen, awer den Duerchgang muss kloer analyséiert ginn. Wann Dir de SRE SLO Prozess benotzt, kënnt d'Verzögerungsufro vum Client oder dem Geschäft, representéiert vum Produktbesëtzer. An eise Service wäert dës Verpflichtung vun Ufank un ouni Astellungen erfëllen!

Ariichten vun engem Test Ëmfeld

Mat Hëllef vun engem Testëmfeld kënne mir eng gemooss Belaaschtung op eise System setzen. Fir Analyse ginn Daten iwwer d'Performance vum Webservice generéiert.

Transaktioun Laascht

Dës Ëmwelt benotzt Vegeta fir e personaliséierten HTTP Ufro Taux ze kreéieren bis gestoppt:

$ 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

Observatioun

Transaktiounsbelaaschtung gëtt während der Runtime applizéiert. Zousätzlech zu der Applikatioun (Zuel vun Ufroen, Äntwertlatenz) a Betribssystem (Erënnerung, CPU, IOPS) Metriken, gëtt d'Applikatiounsprofiléierung ausgeführt fir ze verstoen wou et Problemer huet a wéi d'CPU Zäit verbraucht gëtt.

Profiléieren

Profiléieren ass eng Zort Messung déi Iech erlaabt ze gesinn wou d'CPU Zäit geet wann eng Applikatioun leeft. Et erlaabt Iech genau ze bestëmmen wou a wéi vill Prozessor Zäit verbruecht gëtt:

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Dës Donnéeë kënne während der Analyse benotzt ginn fir Abléck an verschwenden CPU Zäit an onnéideg Aarbecht ze kréien. Go (pprof) kann Profiler generéieren an visualiséieren se als Flam Grafike mat engem Standard Set vun Tools. Ech wäert iwwer hir Benotzung an Installatiounsguide méi spéit am Artikel schwätzen.

Ausféierung, Observatioun, Analyse.

Loosst eis en Experiment maachen. Mir maachen, observéieren an analyséieren bis mir mat der Leeschtung zefridden sinn. Loosst eis en arbiträr niddereg Belaaschtungswäert wielen fir se z'applizéieren fir d'Resultater vun den éischten Observatiounen ze kréien. Bei all nächste Schrëtt wäerte mir d'Belaaschtung mat engem gewësse Skalafaktor erhéijen, mat e puer Variatiounen gewielt. All Laaschttest Laf gëtt mat der Unzuel vun Ufroen ugepasst: make load-test LOAD_TEST_RATE=X.

50 Ufroen pro Sekonn

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Opgepasst op déi zwee Top Grafiken. Uewe lénks weist datt eis Uwendung 50 Ufroe pro Sekonn veraarbecht (et mengt) an uewe riets weist d'Dauer vun all Ufro. Béid Parameteren hëllefen eis ze kucken an ze analyséieren ob mir an eise Leeschtungsgrenze sinn oder net. Rout Linn op der Grafik HTTP Ufro Latenz weist SLO op 60ms. D'Linn weist datt mir wäit ënner eiser maximaler Äntwertzäit sinn.

Loosst eis d'Käschte Säit kucken:

10000 Ufroen pro Sekonn / 50 Ufroe pro Server = 200 Server + 1

Mir kënnen dës Figur nach verbesseren.

500 Ufroen pro Sekonn

Méi interessant Saache fänken un ze geschéien wann d'Laascht op 500 Ufroe pro Sekonn kënnt:

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Nach eng Kéier, an der ieweschter lénkser Grafik kënnt Dir gesinn datt d'Applikatioun normal Belaaschtung ophëlt. Wann dat net de Fall ass, gëtt et e Problem um Server op deem d'Applikatioun leeft. D'Äntwert Latenz Grafik ass uewe riets, a weist datt 500 Ufroe pro Sekonn zu enger Äntwertverzögerung vu 25-40ms gefouert hunn. Den 99. Percentil passt nach ëmmer gutt an de 60ms SLO uewen gewielt.

A punkto Käschten:

10000 Ufroen pro Sekonn / 500 Ufroe pro Server = 20 Server + 1

Alles kann nach verbessert ginn.

1000 Ufroen pro Sekonn

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Grousse Start! D'Applikatioun weist datt et 1000 Ufroe pro Sekonn veraarbecht huet, awer d'Latenzlimit gouf vum SLO verletzt. Dëst kann an der Linn p99 an uewe riets Grafik gesi ginn. Trotz der Tatsaach, datt d'p100 Linn vill méi héich ass, sinn déi tatsächlech Verspéidungen méi héich wéi de Maximum vu 60ms. Loosst eis an d'Profiling tauchen fir erauszefannen wat d'Applikatioun tatsächlech mécht.

Profiléieren

Fir Profiling setzen mir d'Laascht op 1000 Ufroen pro Sekonn, a benotzt dann pprof fir Daten z'erfaassen fir erauszefannen wou d'Applikatioun CPU Zäit verbréngt. Dëst kann gemaach ginn andeems Dir den HTTP-Endpunkt aktivéiert pprof, an dann, ënner Laascht, späichert d'Resultater mat Curl:

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

D'Resultater kënnen esou ugewise ginn:

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

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

D'Grafik weist wou a wéi vill d'Applikatioun CPU Zäit verbréngt. Vun der Beschreiwung vun Brendan Gregg:

D'X-Achs ass d'Stackprofilbevëlkerung, alphabetesch zortéiert (dëst ass keng Zäit), d'Y-Achs weist d'Tiefe vum Stack, zielt vun Null un [uewen]. All Rechteck ass e Stack Frame. Wat méi breet de Frame ass, dest méi dacks ass et an de Stäck präsent. Wat uewen ass leeft op der CPU, a wat drënner ass, sinn d'Kandelementer. D'Faarwen bedeiten normalerweis näischt, mä ginn einfach zoufälleg gewielt fir Frames z'ënnerscheeden.

Analyse - Hypothes

Fir Tuning konzentréiere mir eis op ze probéieren verschwenden CPU Zäit ze fannen. Mir wäerte fir déi gréisste Quelle vun onnëtz Ausgaben kucken an ewechzehuelen. Gutt, well d'Profiling ganz präzis verroden, wou genau d'Applikatioun seng Prozessorzäit verbréngt, musst Dir et e puer Mol maachen, an Dir musst och den Applikatiounsquellcode änneren, d'Tester nei ausféieren a kucken datt d'Leeschtung d'Zil erreecht.

No dem Brendan Gregg seng Empfehlungen liesen mir d'Diagramm vun uewen no ënnen. All Linn weist e Stack Frame (Funktioun Opruff). Déi éischt Zeil ass den Entréespunkt an de Programm, den Elterendeel vun allen aneren Uriff (an anere Wierder, all aner Uriff hunn et op hirem Stack). Déi nächst Zeil ass schonn anescht:

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Wann Dir de Cursor iwwer den Numm vun enger Funktioun op der Grafik hovert, gëtt d'Gesamtzäit déi se um Stack wärend dem Debugging war ugewisen. D'HTTPServe Funktioun war do 65% vun der Zäit, aner Runtime Funktiounen runtime.mcall, mstart и gc, huet de Rescht vun der Zäit opgeholl. Spaass Tatsaach: 5% vun der Gesamtzäit gëtt op DNS Ufroen verbruecht:

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

D'Adressen, déi de Programm sicht, gehéieren zu Postgresql. Klickt op FindByAge:

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Interessanterweis weist de Programm datt et am Prinzip dräi Haaptquellen sinn, déi Verspéidungen addéieren: Verbindungen opmaachen an zoumaachen, Daten froen a Verbindung mat der Datebank. D'Grafik weist datt DNS Ufroen, Ouverture a Schließverbindungen ongeféier 13% vun der Gesamt Ausféierungszäit huelen.

Hypothese: D'Wiederbenotzung vu Verbindunge mat Pooling soll d'Zäit vun enger eenzeger HTTP-Ufro reduzéieren, wat méi héicht Duerchput a méi niddereg latency erlaabt.

Opstellung vun der Applikatioun - Experiment

Mir aktualiséieren de Quellcode, probéiert d'Verbindung op Postgresql fir all Ufro ze läschen. Déi éischt Optioun ass ze benotzen Verbindung Pool um Applikatiounsniveau. An dësem Experiment hu mir loosst eis et opstellen Verbindung Pooling mam SQL Driver fir Go:

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

if err != nil {
   return nil, err
}

Ausféierung, Observatioun, Analyse

Nodeems Dir den Test mat 1000 Ufroen pro Sekonn nei gestart huet, ass et kloer datt d'Latenzniveauen vum p99 mat engem SLO vun 60ms zréck op normal sinn!

Wat sinn d'Käschte?

10000 Ufroen pro Sekonn / 1000 Ufroe pro Server = 10 Server + 1

Loosst eis et nach besser maachen!

2000 Ufroen pro Sekonn

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

D'Verdueblung vun der Belaaschtung weist déiselwecht Saach, déi iewescht lénks Grafik weist datt d'Applikatioun et fäerdeg bréngt 2000 Ufroe pro Sekonn ze veraarbecht, p100 ass manner wéi 60ms, p99 erfëllt den SLO.

A punkto Käschten:

10000 Ufroen pro Sekonn / 2000 Ufroe pro Server = 5 Server + 1

3000 Ufroen pro Sekonn

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Hei kann d'Applikatioun 3000 Ufroe mat enger p99 Latenz vu manner wéi 60ms veraarbechten. De SLO gëtt net verletzt, an d'Käschte gi wéi follegt ugeholl:

10000 Ufroen pro Sekonn / pro 3000 Ufroe pro Server = 4 Server + 1 (den Auteur huet ofgerënnt, ca. Iwwersetzer)

Loosst eis eng aner Ronn Analys probéieren.

Analyse - Hypothes

Mir sammelen a weisen d'Resultater vum Debugging vun der Applikatioun bei 3000 Ufroen pro Sekonn:

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Nach ëmmer gëtt 6% vun der Zäit fir Verbindungen opgestallt. D'Ariichten vum Pool huet d'Performance verbessert, awer Dir kënnt nach ëmmer gesinn datt d'Applikatioun weider schafft fir nei Verbindunge mat der Datebank ze kreéieren.

Hypothese: D'Verbindungen, trotz der Präsenz vun engem Pool, ginn nach ëmmer erofgelooss a gebotzt, sou datt d'Applikatioun se muss zréckgesat ginn. D'Zuel vun de pendingverbindunge fir d'Poolgréisst setzen soll mat Latenz hëllefe andeems d'Zäit miniméiert déi d'Applikatioun verbréngt eng Verbindung ze kreéieren.

Opstellung vun der Applikatioun - Experiment

Probéiert ze installéieren MaxIdleConns gläich mat der Poolgréisst (och beschriwwen hei):

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

Ausféierung, Observatioun, Analyse

3000 Ufroen pro Sekonn

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

p99 ass manner wéi 60ms mat wesentlech manner p100!

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Iwwerpréift vun der Flamgrafik weist datt d'Verbindung net méi opfälleg ass! Loosst eis méi detailléiert kucken pg(*conn).query - mir bemierken och net datt d'Verbindung hei opgebaut gëtt.

SRE: Leeschtung Analyse. Konfiguratiounsmethod mat engem einfachen Webserver am Go

Konklusioun

Leeschtungsanalyse ass kritesch fir ze verstoen datt Clienterwaardungen an net-funktionell Ufuerderunge erfëllt ginn. Analyse duerch d'Vergläiche vun Observatioune mat Client Erwaardungen kann hëllefen ze bestëmmen wat akzeptabel ass a wat net. Go bitt mächteg Tools, déi an der Standardbibliothéik agebaut sinn, déi d'Analyse einfach an zougänglech maachen.

Source: will.com

Setzt e Commentaire