Kot v
Nekega dne sem se zbudil z nezadovoljnim e-poštnim sporočilom zaradi dolgih zamud z Alvinom, ki smo ga načrtovali lansirati v bližnji prihodnosti. Natančneje, odjemalec je doživel zakasnitev 99. percentila v območju 50 ms, kar je precej nad našim proračunom za zakasnitev. To je bilo presenetljivo, saj sem storitev obsežno testiral, zlasti glede zakasnitve, kar je pogosta pritožba.
Preden sem dal Alvina v testiranje, sem izvedel veliko poskusov s 40 poizvedbami na sekundo (QPS), pri čemer so vsi pokazali zakasnitev manj kot 10 ms. Bil sem pripravljen izjaviti, da se ne strinjam z njihovimi rezultati. Ko pa sem ponovno pogledal pismo, sem opazil nekaj novega: nisem natančno testiral pogojev, ki so jih omenili, njihov QPS je bil precej nižji od mojega. Testiral sem pri 40k QPS, oni pa le pri 1k. Izvedel sem še en poskus, tokrat z nižjim QPS, samo da bi jih pomiril.
Ker pišem blog o tem, ste verjetno že ugotovili, da so bile njihove številke pravilne. Svojega virtualnega odjemalca sem testiral znova in znova z enakim rezultatom: majhno število zahtev ne le poveča zakasnitev, ampak poveča število zahtev z zakasnitvijo več kot 10 ms. Z drugimi besedami, če je pri 40k QPS približno 50 zahtev na sekundo preseglo 50 ms, potem je bilo pri 1k QPS vsako sekundo 100 zahtev nad 50 ms. Paradoks!
Zoženje iskanja
Ko se soočite s težavo z zakasnitvijo v porazdeljenem sistemu z veliko komponentami, je prvi korak ustvariti kratek seznam osumljencev. Poglobimo se nekoliko globlje v Alvinovo arhitekturo:
Dobro izhodišče je seznam dokončanih V/I prehodov (omrežni klici/iskanje diska itd.). Poskusimo ugotoviti, kje je zamuda. Poleg očitnega V/I z odjemalcem Alvin naredi dodaten korak: dostopa do shrambe podatkov. Vendar pa ta shramba deluje v isti gruči kot Alvin, zato bi morala biti tam zakasnitev manjša kot pri odjemalcu. Torej, seznam osumljencev:
- Omrežni klic od stranke do Alvina.
- Omrežni klic Alvina v shrambo podatkov.
- Iskanje na disku v shrambi podatkov.
- Omrežni klic iz podatkovnega skladišča Alvinu.
- Omrežni klic Alvina stranki.
Poskusimo nekaj točk prečrtati.
Shranjevanje podatkov nima nič s tem
Prva stvar, ki sem jo naredil, je bila pretvorba Alvina v strežnik ping-ping, ki ne obdeluje zahtev. Ko prejme zahtevo, vrne prazen odgovor. Če se zakasnitev zmanjša, potem napaka v implementaciji Alvina ali podatkovnega skladišča ni nič nezaslišanega. V prvem poskusu dobimo naslednji graf:
Kot lahko vidite, pri uporabi strežnika ping-ping ni izboljšav. To pomeni, da podatkovno skladišče ne poveča zakasnitve, seznam osumljencev pa se prepolovi:
- Omrežni klic od stranke do Alvina.
- Omrežni klic Alvina stranki.
Super! Seznam se hitro krči. Mislil sem, da sem skoraj ugotovil razlog.
gRPC
Zdaj je čas, da vam predstavim novega igralca: gRPC
dobro optimiziran in pogosto uporabljen, to je bilo prvič, da sem ga uporabljal v sistemu te velikosti in pričakoval sem, da bo moja izvedba neoptimalna - milo rečeno.
razpoložljivost gRPC
v skladu je povzročil novo vprašanje: morda je to moja implementacija ali jaz gRPC
povzroča težave z zakasnitvijo? Dodajanje novega osumljenca na seznam:
- Naročnik pokliče knjižnico
gRPC
- Knjižnica
gRPC
opravi omrežni klic v knjižnico na odjemalcugRPC
na strežniku - Knjižnica
gRPC
stiki Alvin (brez delovanja v primeru strežnika za ping-pong)
Da bi vam predstavili, kako izgleda koda, moja implementacija odjemalec/Alvin ni veliko drugačna od implementacije odjemalec-strežnik
Opomba: zgornji seznam je nekoliko poenostavljen, ker
gRPC
omogoča uporabo lastnega (predloga?) modela navojev, v katerem je izvajalni sklad prepletengRPC
in uporabniška implementacija. Zaradi enostavnosti se bomo držali tega modela.
Profiliranje bo vse popravilo
Ko sem prečrtal shrambo podatkov, sem mislil, da sem skoraj končal: »Zdaj je enostavno! Uporabimo profil in ugotovimo, kje prihaja do zamude.« jaz
Vzel sem štiri profile: z visokim QPS (nizka zakasnitev) in s strežnikom za ping-pong z nizkim QPS (visoka zakasnitev), tako na strani odjemalca kot na strani strežnika. In za vsak slučaj sem vzel tudi vzorčni profil procesorja. Ko primerjam profile, običajno iščem neobičajen sklad klicev. Na primer, na slabi strani z visoko zakasnitvijo je veliko več preklopov konteksta (10-krat ali več). Toda v mojem primeru je bilo število preklopov konteksta skoraj enako. Na mojo grozo tam ni bilo nič pomembnega.
Dodatno odpravljanje napak
Bil sem obupan. Nisem vedel, katera druga orodja bi lahko uporabil, in moj naslednji načrt je bil v bistvu ponoviti poskuse z različnimi različicami, namesto da bi jasno diagnosticiral težavo.
Kaj če
Že od samega začetka me je skrbela specifična zakasnitev 50 ms. To je zelo velik čas. Odločil sem se, da bom iz kode izrezal dele, dokler ne bom natančno ugotovil, kateri del povzroča to napako. Potem je prišel poskus, ki je deloval.
Kot ponavadi se za nazaj zdi, da je bilo vse očitno. Odjemalca sem postavil na isti stroj kot Alvin - in poslal zahtevo na localhost
. In povečanja zakasnitve ni več!
Nekaj je bilo narobe z omrežjem.
Učenje veščin omrežnega inženirja
Moram priznati: moje znanje o omrežnih tehnologijah je grozljivo, sploh glede na to, da z njimi delam vsak dan. Toda omrežje je bilo glavni osumljenec in moral sem se naučiti, kako ga odpraviti.
Na srečo ima internet rad tiste, ki se želijo učiti. Kombinacija pinga in tracerta se je zdela dovolj dober začetek za odpravljanje težav pri omrežnem transportu.
Najprej sem zagnal
Potem sem poskusil
Zakasnitev torej ni povzročala moja koda, izvedba gRPC ali omrežje. Začelo me je skrbeti, da tega ne bom nikoli razumel.
Zdaj pa na katerem OS-u smo
gRPC
široko uporabljen v Linuxu, a eksotičen v sistemu Windows. Odločil sem se preizkusiti eksperiment, ki je deloval: ustvaril sem virtualni stroj Linux, prevedel Alvina za Linux in ga namestil.
In to se je zgodilo: strežnik za namizni tenis Linux ni imel enakih zamud kot podoben gostitelj Windows, čeprav vir podatkov ni bil nič drugačen. Izkazalo se je, da je težava v implementaciji gRPC za Windows.
Naglov algoritem
Ves ta čas sem mislil, da pogrešam zastavo gRPC
. Zdaj razumem, kaj v resnici je gRPC
Windows zastavica manjka. Našel sem notranjo knjižnico RPC, za katero sem bil prepričan, da bo dobro delovala za vse nastavljene zastavice
Skoraj Končano: dodane zastavice sem začel odstranjevati eno za drugo, dokler se ni vrnila regresija, da sem lahko natančno določil vzrok. Bilo je zloglasno
gRPC
ta zastavica je bila nastavljena v izvedbi Linuxa za vtičnice TCP, ne pa tudi v sistemu Windows. Jaz sem to
Zaključek
Večjo zakasnitev pri nizkih QPS je povzročila optimizacija OS. V retrospektivi profiliranje ni zaznalo zakasnitve, ker je bilo izvedeno v načinu jedra in ne v
Kar se tiče eksperimenta z lokalnim gostiteljem, se verjetno ni dotaknil dejanske omrežne kode in Naglov algoritem se ni zagnal, tako da so težave z zakasnitvijo izginile, ko je odjemalec dosegel Alvina prek lokalnega gostitelja.
Naslednjič, ko opazite povečanje zakasnitve, ko se število zahtev na sekundo zmanjša, bi moral biti Naglov algoritem na vašem seznamu osumljencev!
Vir: www.habr.com