MÔnikord tÀhendab rohkem vÀhem. Kui koormuse vÀhendamine viib latentsuse suurenemiseni

Nii nagu enamikus postitustes, tekkis probleem jaotatud teenusega, nimetame seda teenust Elviniks. Seekord ma ei avastanud probleemi iseseisvalt, mulle rÀÀkisid sellest klienditugi.

Ühel hommikul Ă€rkasin ma rahulolematust kirjast, mille pĂ”hjus oli suured latentsused Elvini juures, mida plaanisime peagi kĂ€ivitada. EelkĂ”ige koges klient 99. protsentiili latentsust umbes 50 ms, mis oli meie latentsuse eelarvest oluliselt kĂ”rgem. See oli ĂŒllatav, kuna olin teenust pĂ”hjalikult testinud, eriti latentsuse osas, mis on sagedane kaebuste teema.

Enne kui andsin Elvini testimiseks, tegin palju katseid 40 000 pĂ€ringut sekundis (QPS) juures, tulemused nĂ€itasid kĂ”ik latentsust alla 10 ms. Olin valmis esitama vĂ€ite, et ma ei nĂ”ustu nende tulemustega. Kuid vaadates uuesti kirja, mĂ€rkasin midagi uut: ma ei olnud testi teinud nende mainitud tingimustes, nende QPS oli oluliselt madalam kui minu. Olin testinud 40k QPS juures, samas kui nemad vaid 1k juures. KĂ€ivitasin veel ĂŒhe katse, seekord madalama QPS-iga, lihtsalt et neid rahuldada.

Kuna ma kirjutan sellest blogis – ilmselt olete juba aru saanud: nende numbrid osutusid Ă”igeks. Olen oma virtuaalset klienti korduvalt kontrollinud, tulemuseks on ikka sama: madal pĂ€ringute arv mitte ainult ei suurenda viivitust, vaid ka pĂ€ringute arvu, mille viivitus ĂŒletab 10 ms. TeisisĂ”nu, kui 40k QPS juures ĂŒletas umbes 50 pĂ€ringut sekundis 50 ms, siis 1k QPS puhul oli iga sekund 100 pĂ€ringut, mis ĂŒletasid 50 ms. Paradoks!

MÔnikord tÀhendab rohkem vÀhem. Kui koormuse vÀhendamine viib latentsuse suurenemiseni

Kitsendame otsinguulatust

Viivituse probleemiga kokku puutudes kompleksse sĂŒsteemi mitme komponendiga tuleb kĂ”igepealt koostada lĂŒhike kahtlusaluste nimekiri. Kaevame veidi sĂŒgavamale Elvini arhitektuuri:

MÔnikord tÀhendab rohkem vÀhem. Kui koormuse vÀhendamine viib latentsuse suurenemiseni

Hea lĂ€htepunkt on teostatud sisendi-vĂ€ljundi ĂŒleminekute (vĂ”rgukutsed/diskid ja jne) nimekiri. Proovime vĂ€lja selgitada, kus on viivitus. Lisaks ilmselgele sisendi-vĂ€ljundile kliendiga, teeb Elvin veel ĂŒhe sammu: ta pöördub andmestikku. Kuid see andmestik töötab koos Elviniga ĂŒhes klastris, seega peab sealne viivitus olema vĂ€iksem kui kliendiga. Seega, kahtlusaluste nimekiri:

  1. Kliendi vÔrgu kutsumine Elvinile.
  2. Elvin'i andmehoidla vÔrgu kÔne.
  3. Andmehoidla kettalt otsing.
  4. Andmehoidla kÔne Elvin'ist.
  5. Elvin'i ja kliendi vahel vÔrgu kÔne.

Proovime mÔned punktid vÀlja jÀtta.

Andmehoidla ei mÀngi rolli.

Esimesena muutsin Elvin'i ping-ping serveriks, mis ei töötle pĂ€ringuid. PĂ€ringu saades tagastab ta tĂŒhja vastuse. Kui latentsus vĂ€heneb, siis on viga kas Elvin'is vĂ”i andmehoidlas — midagi ebatavalist. Esimeses eksperimendis saime sellise graafiku:

MÔnikord tÀhendab rohkem vÀhem. Kui koormuse vÀhendamine viib latentsuse suurenemiseni

Nagu nÀeme, ei ole ping-ping serveri kasutamisel mingeid parandusi. See tÀhendab, et andmehoidla ei suurenda latentsust ja kahtlusaluste nimekiri vÀheneb poole vÔrra:

  1. Kliendi vÔrgu kutsumine Elvinile.
  2. Elvin'i ja kliendi vahel vÔrgu kÔne.

SuurepÀrane! Nimekiri vÀheneb kiiresti. Arvasin, et olen peaaegu pÔhjuse vÀlja selgitanud.

gRPC

NĂŒĂŒd on Ă”ige aeg tutvustada teile uut mĂ€ngijat: gRPC. See on Google'i avatud lĂ€htekoodiga teek sisemiseks protsessidevaheliseks suhtlemiseks. RPC. Kuigi gRPC on hĂ€sti optimeeritud ja laialdaselt kasutatav, kasutasin ma seda esmakordselt sellise suurusega sĂŒsteemis ja ootasin, et minu rakendus oleks vĂ€hem optimeeritud — Ă”rnalt öeldes.

Olemasolu gRPC steigis tekitas uue kĂŒsimuse: vĂ”ib-olla on see minu rakendus vĂ”i gRPC tekitab probleemi viivitusega? Lisame uue kahtlusaluse nimekirja:

  1. Kliendi poolt kutsutakse esile raamatukogu gRPC
  2. Raamatukogu gRPC vÔrgukÔne teostamiseks raamatukogu kliendis gRPC serveris
  3. Raamatukogu gRPC suunab Elvinile (ping-pongi serveri juhtumitel ei toimu operatsioone)

Et mĂ”ista, milline nĂ€eb vĂ€lja kood, ei erine minu kliendi/Elvini rakendus oluliselt kliendi-serveri asĂŒnkroonsete nĂ€idete.

MĂ€rkus: ĂŒlaltoodud nimekiri on veidi lihtsustatud, kuna gRPC see vĂ”imaldab kasutada oma (mustriga?) voolumudelit, kus kassa tĂ€itmise gRPC ja kasutaja rakendus on pĂ”imunud. Lihtsuse huvides jÀÀme selle mudeli juurde.

Profiliseerimine parandab kÔik

Andmesalvestuste eemaldamisel mĂ”tlesin, et peaaegu lĂ”petasin: „NĂŒĂŒd on lihtne! Rakendame profiili ja vaatame, kus viivitus tekib.” Mina olen tĂ€pse profiliseerimise suur austaja, sest kuna CPU on vĂ€ga kiire ning tavaliselt ei ole see kitsaskohaks. Enamik viivitustest tekib siis, kui protsessor peab töötamise peatama, et midagi muud teha. TĂ€pne CPU profiilimine on selleks, et tĂ€pselt salvestada kĂ”ik kontekstivahetused ja aru saada, kus viivitused tekivad.

VĂ”tsin neli profiili: kĂ”rgendatud QPS (vĂ€ike viivitus) ja ping-pong server madala QPS-iga (suur viivitus), nii kliendi kui ka serveri kĂŒljelt. Ja igaks juhuks vĂ”tsin ka protsessori profiili. Profiilide vĂ”rdlemisel otsin tavaliselt anomaalset funktsioonide virna. NĂ€iteks kĂ”rge viivitusega nĂ”rgas kĂŒljel toimub palju rohkem kontekstivahetusi (10 ja rohkem korda). Kuid minu puhul oli kontekstivahetuste arv praktiliselt sama. Minu Ă”uduseks ei leidnud ma sealt midagi olulist.

TÀiendav tÔrkeotsing

Olin meeleheites. Ma ei teadnud, milliseid tööriistu veel kasutada, ja minu jÀrgmine plaan seisnes peamiselt katsete kordamises erinevate variantide abil, mitte probleemide selges diagnoosimises.

Mis siis, kui

Algusest peale muretsesin 50 ms latentsuse pÀrast. See on vÀga pikk aeg. Otsustasin, et hakkan koodist osi vÀlja lÔikama, kuni suudan tÀpselt vÀlja selgitada, milline osa tekitab vea. JÀrgmine eksperiment töötas.

Kuidas tavaliselt, tagantjĂ€rele tundub, et kĂ”ik oli ilmne. Asetasin kliendi ĂŒhte masinasse Elviniga — ja saatsin pĂ€ringu localhost. Latentsus suurenes ja kadus!

MÔnikord tÀhendab rohkem vÀhem. Kui koormuse vÀhendamine viib latentsuse suurenemiseni

Midagi polnud vÔrku rahuldav.

Õppida vĂ”rguinseneri oskusi

Pean tunnistama: minu teadmised vÔrgutehnoloogiatest on kohutavad, arvestades, et töötan nendega iga pÀev. Kuid vÔrk oli peamine kahtlusalune ja ma pidin Ôppima, kuidas seda tÔrkeotsida.

Õnneks armastab internet neid, kes tahavad Ă”ppida. Ping ja tracert tundusid olevat piisavalt hea algus vĂ”rgu transportimise probleemide tĂ”rkeotsimiseks.

Esiteks kĂ€ivitasin PsPing TCP-pordile Alvinile. Kasutasin vaikimisi seadeid — mitte midagi erilist. Üle tuhande pingi hulgas ei ĂŒletanud ĂŒkski 10 ms, vĂ€lja arvatud esimene soojenduseks. See on vastuolus 99. protsendi puhul mĂ€rgatud viivituse suurenemisega 50 ms: seal peaksime iga 100 pĂ€ringu kohta nĂ€gema umbes ĂŒhte pĂ€ringut, mille viivitus on 50 ms.

SeejÀrel proovisin tracert: vÔib-olla on probleem mÔnes sÔlmes, mis asub marsruudi vahel Alvinist kliendini. Kuid jÀlgimise tulemused ei toonud samuti midagi kÀega katsuda.

Nii et viivituse pÔhjuseks ei olnud minu kood, gRPC teostus ega vÔrk. Olen juba hakanud muretsema, et ei saa seda kunagi selgeks.

NĂŒĂŒd, millisel operatsioonisĂŒsteemil me oleme

gRPC on Linuxis laialdaselt kasutatav, kuid Windowsis on see eksootika. Otsustasin lÀbi viia eksperimenti, mis osutus edukaks: lÔin Linuxi virtuaalmasina, kompileerisin Alvin Linuxile ja seadistasin selle.

MÔnikord tÀhendab rohkem vÀhem. Kui koormuse vÀhendamine viib latentsuse suurenemiseni

Ja siin on, mis vÀlja tuli: Linuxi ping-pong serveris ei olnud viivitusi nagu sarnasel Windowsi sÔlmel, kuigi andmeallikas ei olnud erinev. Selgub, et probleem on gRPC teostuses Windowsis.

Nagle'i algoritm

Mitu korda arvasin, et mul on lipust puudu gRPC. NĂŒĂŒd sain aru, et see on tegelikult tugevuses gRPC Windowsi lipseb. Leidsin sisemise RPC teegi, mille uskusin töötavat kĂ”ikide paigaldatud lipudega. Winsock. Siis lisasin kĂ”ik need lipud gRPC-sse ja juurutasin Elvini Windowsile, parandatud ping-pongi serveris Windowsis!

MÔnikord tÀhendab rohkem vÀhem. Kui koormuse vÀhendamine viib latentsuse suurenemiseni

Peaaegu valmis: hakkasin eemaldama lisatud lippe ĂŒksainus, kuni regressioon tagasi tuli, et saaksin tĂ€pselt selle pĂ”hjuse kindlaks teha. See oli tuntud TCP_NODELAY, Nagle'i algoritmi lĂŒliti.

Nagle'i algoritm pĂŒĂŒab vĂ€hendada vĂ”rgus saadetud pakettide arvu, viies sĂ”numite edastamise viivituse kuni paketi suurus ĂŒletab teatud baitide arvu. Kuigi see vĂ”ib olla meeldiv tavalise kasutaja jaoks, on see hĂ€vitav reaalajas serverite jaoks, kuna opsĂŒsteem viivitab teatud sĂ”numite edastamisega, pĂ”hjustades viivitusi madala QPS-i korral. gRPC See lipp oli seadistatud Linuxi teostuses TCP socketite jaoks, kuid mitte Windowsis. Ma selle parandasin..

KokkuvÔte

Suur viivitus madala QPS-i tĂ”ttu oli tingitud opsĂŒsteemi optimeerimisest. Tagasi vaadates ei leidnud profilter viivitust, kuna see viidi lĂ€bi tuumikureĆŸiimis, mitte kasutajareĆŸiimis.. Ma ei tea, kas Neiglandi algoritmi on vĂ”imalik jĂ€lgida ETW kaudu, kuid see oleks huvitav.

Mis puutub localhosti eksperimenti, siis see ei hÔlmanud tÔenÀoliselt tegelikku vÔrguedastust ning Neiglandi algoritm ei kÀivitatud, mistÔttu viivitusprobleemid kadusid, kui klient pöördus Elvini poole localhosti kaudu.

JÀrgmine kord, kui mÀrkate viivituse suurenemist, kui sekundis tehtavate pÀringute arv vÀheneb, peaks Neiglandi algoritm olema teie kahtlusaluste nimekirjas!

Allikas: habr.com

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster