SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Analizo kaj agordado de rendimento estas potenca ilo por kontroli rendimentan konformecon por klientoj.

Efikec-analizo povas esti uzata por kontroli proplempunktojn en programo aplikante sciencan aliron al testado de agordaj eksperimentoj. Ĉi tiu artikolo difinas ĝeneralan aliron al rendimenta analizo kaj agordado, uzante Go-retservilon kiel ekzemplon.

Go estas precipe bona ĉi tie ĉar ĝi havas profilajn ilojn pprof en la norma biblioteko.

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

La Strategio

Ni kreu resuman liston por nia struktura analizo. Ni provos uzi iujn datumojn por fari decidojn anstataŭ fari ŝanĝojn bazitajn sur intuicio aŭ divenado. Por fari tion ni faros ĉi tion:

  • Ni determinas la optimumigajn limojn (postuloj);
  • Ni kalkulas la transakcian ŝarĝon por la sistemo;
  • Ni plenumas la teston (kreu datumojn);
  • Ni observas;
  • Ni analizas - ĉu ĉiuj postuloj estas plenumitaj?
  • Ni starigas ĝin science, faras hipotezon;
  • Ni faras eksperimenton por testi ĉi tiun hipotezon.

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Simpla HTTP-Servila Arkitekturo

Por ĉi tiu artikolo ni uzos malgrandan HTTP-servilon en Golang. Ĉiuj kodoj de ĉi tiu artikolo troveblas tie.

La analizita aplikaĵo estas HTTP-servilo, kiu sondas Postgresql por ĉiu peto. Aldone, ekzistas Prometheus, node_exporter kaj Grafana por kolekti kaj montri aplikaĵon kaj sistemajn metrikojn.

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Por simpligi, ni konsideras, ke por horizontala skalo (kaj simpligado de kalkuloj) ĉiu servo kaj datumbazo estas deplojitaj kune:

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Difinante celojn

Je ĉi tiu paŝo, ni decidas pri la celo. Kion ni provas analizi? Kiel ni scias, kiam estas tempo por fini? En ĉi tiu artikolo, ni imagu, ke ni havas klientojn kaj ke nia servo prilaboros 10 petojn sekundo.

В Guglo SRE-Libro Metodoj de elekto kaj modelado estas diskutitaj detale. Ni faru la samon kaj konstruu modelojn:

  • Latenteco: 99% de petoj devas esti kompletigitaj en malpli ol 60ms;
  • Kosto: La servo devus konsumi la minimuman monsumon, kiun ni opinias racie ebla. Por fari tion, ni maksimumigas trairon;
  • Kapacitplanado: Postulas komprenon kaj dokumentadon kiom da okazoj de la aplikaĵo devos esti rulitaj, inkluzive de totala skampla funkcieco, kaj kiom da okazoj estos bezonataj por plenumi komencajn ŝarĝojn kaj provizajn postulojn. redundo n+1.

Latenteco povas postuli optimumigo aldone al analizo, sed trairo klare devas esti analizita. Kiam vi uzas la SRE SLO-procezon, la prokrasta peto venas de la kliento aŭ komerco, reprezentita de la produktposedanto. Kaj nia servo plenumos ĉi tiun devon de la komenco sen ajna agordo!

Agordi testan medion

Helpe de testa medio, ni povos meti mezuran ŝarĝon sur nian sistemon. Por analizo, datumoj pri la agado de la retservo estos generitaj.

Transakcia ŝarĝo

Ĉi tiu medio uzas Vegeta krei kutiman HTTP-peton-procenton ĝis haltigo:

$ 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

Observado

Transakcia ŝarĝo estos aplikata ĉe rultempo. Aldone al aplikaĵo (nombro da petoj, responda latenteco) kaj operaciumo (memoro, CPU, IOPS) metrikoj, aplikaĵoprofilado estos rulita por kompreni kie ĝi havas problemojn kaj kiel CPU-tempo estas konsumita.

Profilado

Profilado estas speco de mezurado kiu permesas vin vidi kien CPU-tempo iras kiam aplikaĵo funkcias. Ĝi permesas vin determini precize kie kaj kiom da procesora tempo estas pasigita:

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Ĉi tiuj datumoj povas esti uzataj dum analizo por akiri sciojn pri malŝparita CPU-tempo kaj nenecesa laboro farita. Go (pprof) povas generi profilojn kaj bildigi ilin kiel flamajn grafikojn uzante norman aron de iloj. Mi parolos pri ilia uzo kaj aranĝo gvidilo poste en la artikolo.

Ekzekuto, observado, analizo.

Ni faru eksperimenton. Ni plenumos, observos kaj analizos ĝis ni kontentiĝos pri la agado. Ni elektu arbitre malaltan ŝarĝvaloron por apliki ĝin por akiri la rezultojn de la unuaj observoj. Ĉe ĉiu posta paŝo ni pliigos la ŝarĝon kun certa skala faktoro, elektita kun iu vario. Ĉiu ŝarĝotesto estas farita kun la nombro da petoj alĝustigita: make load-test LOAD_TEST_RATE=X.

50 petoj por sekundo

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Atentu la suprajn du grafikaĵojn. La supra maldekstre montras, ke nia aplikaĵo procesas 50 petojn sekundo (ĝi pensas) kaj la supra dekstre montras la daŭron de ĉiu peto. Ambaŭ parametroj helpas nin rigardi kaj analizi ĉu ni estas ene de niaj rendimentaj limoj aŭ ne. Ruĝa linio sur la grafikaĵo HTTP-Peto Latenteco montras SLO je 60ms. La linio montras, ke ni estas multe sub nia maksimuma responda tempo.

Ni rigardu la kostan flankon:

10000 50 petoj por sekundo / 200 petoj per servilo = 1 serviloj + XNUMX

Ni ankoraŭ povas plibonigi ĉi tiun ciferon.

500 petoj por sekundo

Pli interesaj aferoj komencas okazi kiam la ŝarĝo atingas 500 petojn sekundo:

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Denove, en la supra maldekstra grafikaĵo vi povas vidi, ke la aplikaĵo registras normalan ŝarĝon. Se ĉi tio ne estas la kazo, estas problemo sur la servilo sur kiu la aplikaĵo funkcias. La responda latenteca grafiko situas supre dekstre, montrante, ke 500 petoj sekundo rezultigis respondmalfruon de 25-40ms. La 99-a percentilo ankoraŭ bone kongruas en la 60ms SLO elektitan supre.

Laŭ kosto:

10000 500 petoj por sekundo / 20 petoj per servilo = 1 serviloj + XNUMX

Ĉio ankoraŭ povas esti plibonigita.

1000 petoj por sekundo

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Bonega lanĉo! La aplikaĵo montras, ke ĝi prilaboris 1000 petojn sekundo, sed la latencia limo estis malobservita de la SLO. Ĉi tio videblas en linio p99 en la supra dekstra grafikaĵo. Malgraŭ la fakto, ke la p100-linio estas multe pli alta, la realaj prokrastoj estas pli altaj ol la maksimumo de 60ms. Ni plonĝu en profiladon por ekscii, kion efektive faras la aplikaĵo.

Profilado

Por profilado, ni agordas la ŝarĝon al 1000 petoj sekundo, tiam uzu pprof kapti datumojn por ekscii kie la aplikaĵo pasigas CPU-tempon. Ĉi tio povas esti farita per aktivigo de la HTTP-finpunkto pprof, kaj tiam, sub ŝarĝo, konservu la rezultojn per buklo:

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

La rezultoj povas esti montrataj jene:

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

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

La grafikaĵo montras kie kaj kiom la aplikaĵo pasigas CPU-tempon. El la priskribo de Brendan Gregg:

La X-akso estas la staka profilpopulacio, ordigita alfabete (ĉi tio ne estas tempo), la Y-akso montras la profundon de la stako, kalkulante de nulo ĉe [supro]. Ĉiu rektangulo estas staka kadro. Ju pli larĝa la kadro, des pli ofte ĝi ĉeestas en la stakoj. Kio estas supre funkcias per la CPU, kaj kio estas sube estas la infanaj elementoj. La koloroj kutime ne signifas ion ajn, sed estas simple elektitaj hazarde por diferencigi kadrojn.

Analizo - hipotezo

Por agordado, ni fokusos provi trovi malŝparitan CPU-tempon. Ni serĉos la plej grandajn fontojn de senutila elspezo kaj forigos ilin. Nu, pro tio, ke profilado malkaŝas tre precize, kie precize la aplikaĵo pasigas sian procesoran tempon, vi eble devos fari ĝin plurfoje, kaj vi ankaŭ devos ŝanĝi la fontkodon de la aplikaĵo, refari la testojn kaj vidi, ke rendimento alproksimiĝas al la celo.

Sekvante la rekomendojn de Brendan Gregg, ni legos la diagramon de supre ĝis malsupre. Ĉiu linio montras stakan kadron (funkcivoko). La unua linio estas la enirpunkto en la programon, la gepatro de ĉiuj aliaj vokoj (alivorte, ĉiuj aliaj vokoj havos ĝin sur sia stako). La sekva linio jam estas malsama:

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Se vi ŝvebas la kursoron super la nomo de funkcio sur la grafikaĵo, la tuta tempo, kiam ĝi estis sur la stako dum sencimigo, estos montrata. La funkcio HTTPServe estis tie 65% de la tempo, aliaj rultempaj funkcioj runtime.mcall, mstart и gc, okupis la reston de la tempo. Amuza fakto: 5% de la tuta tempo estas pasigitaj por DNS-demandoj:

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

La adresoj, kiujn la programo serĉas, apartenas al Postgresql. Alklaku FindByAge:

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Interese, ke la programo montras, ke principe ekzistas tri ĉefaj fontoj, kiuj aldonas prokrastojn: malfermi kaj fermi konektojn, peti datumojn kaj konekti al la datumbazo. La grafikaĵo montras, ke DNS-petoj, malfermaj kaj fermaj konektoj okupas ĉirkaŭ 13% de la tuta ekzekuttempo.

Hipotezo: Reuzo de konektoj uzantaj kunigon devus redukti la tempon de ununura HTTP-peto, permesante pli altan trairon kaj pli malaltan latentecon..

Agordo de la aplikaĵo - eksperimento

Ni ĝisdatigas la fontkodon, provas forigi la konekton al Postgresql por ĉiu peto. La unua opcio estas uzi konekta naĝejo ĉe la aplika nivelo. En ĉi tiu eksperimento ni ni starigu ĝin konekto-kunigo uzante sql-ŝoforon por iri:

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

if err != nil {
   return nil, err
}

Ekzekuto, observado, analizo

Post rekomenco de la testo kun 1000 petoj sekundo, estas klare, ke la latenciaj niveloj de p99 normaliĝis kun SLO de 60ms!

Kio estas la kosto?

10000 1000 petoj por sekundo / 10 petoj per servilo = 1 serviloj + XNUMX

Ni faru ĝin eĉ pli bone!

2000 petoj por sekundo

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Duobligi la ŝarĝon montras la samon, la supra maldekstra grafikaĵo montras, ke la aplikaĵo sukcesas prilabori 2000 petojn sekundo, p100 estas pli malalta ol 60ms, p99 kontentigas la SLO.

Laŭ kosto:

10000 2000 petoj por sekundo / 5 petoj per servilo = 1 serviloj + XNUMX

3000 petoj por sekundo

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Ĉi tie la aplikaĵo povas procesi 3000 petojn kun p99-latenteco de malpli ol 60ms. La SLO ne estas malobservita, kaj la kosto estas akceptita jene:

10000 petoj por sekundo / po 3000 petoj per servilo = 4 serviloj + 1 (la aŭtoro rondigis, ĉ. tradukisto)

Ni provu alian analizon.

Analizo - hipotezo

Ni kolektas kaj montras la rezultojn de elpurigado de la aplikaĵo je 3000 petoj sekundo:

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Ankoraŭ 6% de la tempo estas elspezitaj por establi ligojn. Agordo de la naĝejo plibonigis rendimenton, sed vi ankoraŭ povas vidi, ke la aplikaĵo daŭre funkcias por krei novajn konektojn al la datumbazo.

Hipotezo: Konektoj, malgraŭ la ĉeesto de naĝejo, ankoraŭ estas forigitaj kaj purigitaj, do la aplikaĵo bezonas restarigi ilin. Agordi la nombron da pritraktataj konektoj al la naĝejo-grandeco devus helpi kun latenteco minimumigante la tempon, kiun la aplikaĵo pasigas por krei konekton..

Agordo de la aplikaĵo - eksperimento

Provante instali MaxIdleConns egala al la naĝejo (ankaŭ priskribita tie):

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

Ekzekuto, observado, analizo

3000 petoj por sekundo

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

p99 estas malpli ol 60ms kun signife malpli p100!

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

Kontroli la flamgrafikon montras, ke la konekto ne plu rimarkeblas! Ni kontrolu pli detale pg(*conn).query — ni ankaŭ ne rimarkas, ke la rilato estas establita ĉi tie.

SRE: Efikeco-Analizo. Agorda metodo uzante simplan retservilon en Go

konkludo

Analizo de rendimento estas kritika por kompreni, ke atendoj de kliento kaj nefunkciaj postuloj estas plenumitaj. Analizo komparante observaĵojn kun klientaj atendoj povas helpi determini kio estas akceptebla kaj kio ne. Go provizas potencajn ilojn enkonstruitajn en la norma biblioteko, kiuj faras analizon simpla kaj alirebla.

fonto: www.habr.com

Aldoni komenton