Kao u
Jednog dana probudio me nezadovoljan e-mail zbog dugih kašnjenja s Alvinom, koji smo planirali pokrenuti u bliskoj budućnosti. Konkretno, klijent je doživio 99. percentil kašnjenja u području od 50 ms, znatno iznad našeg proračuna kašnjenja. To je bilo iznenađujuće jer sam opsežno testirao uslugu, posebno na latenciju, što je uobičajena pritužba.
Prije nego što sam Alvina stavio na testiranje, proveo sam mnogo eksperimenata s 40 tisuća upita u sekundi (QPS), a svi su pokazali kašnjenje manje od 10 ms. Bio sam spreman izjaviti da se ne slažem s njihovim rezultatima. No, bacivši još jedan pogled na pismo, primijetio sam nešto novo: nisam točno testirao uvjete koje su spomenuli, njihov QPS bio je puno niži od mog. Testirao sam na 40k QPS, ali oni samo na 1k. Izveo sam još jedan eksperiment, ovaj put s nižim QPS-om, samo da ih umirim.
Budući da pišem blog o ovome, vjerojatno ste već shvatili da su njihove brojke bile točne. Testirao sam svoj virtualni klijent uvijek iznova, s istim rezultatom: mali broj zahtjeva ne samo da povećava latenciju, već povećava i broj zahtjeva s latencijom većom od 10 ms. Drugim riječima, ako je pri 40k QPS oko 50 zahtjeva u sekundi premašilo 50 ms, tada je pri 1k QPS bilo 100 zahtjeva iznad 50 ms svake sekunde. Paradoks!
Sužavanje pretrage
Kada se suočite s problemom kašnjenja u distribuiranom sustavu s mnogo komponenti, prvi korak je stvoriti kratki popis osumnjičenih. Zaronimo malo dublje u Alvinovu arhitekturu:
Dobra polazna točka je popis dovršenih I/O prijelaza (mrežni pozivi/traženje diska, itd.). Pokušajmo otkriti gdje je kašnjenje. Osim očitog I/O s klijentom, Alvin poduzima dodatni korak: pristupa pohrani podataka. Međutim, ova pohrana radi u istom klasteru kao Alvin, tako da bi latencija tamo trebala biti manja nego kod klijenta. Dakle, popis osumnjičenih:
- Mrežni poziv od klijenta do Alvina.
- Mrežni poziv od Alvina prema pohrani podataka.
- Pretraživanje na disku u pohrani podataka.
- Mrežni poziv iz skladišta podataka Alvinu.
- Mrežni poziv od Alvina klijentu.
Pokušajmo prekrižiti neke točke.
Pohrana podataka nema nikakve veze s tim
Prvo što sam učinio je pretvoriti Alvina u ping-ping poslužitelj koji ne obrađuje zahtjeve. Kada primi zahtjev, vraća prazan odgovor. Ako se latencija smanji, tada greška u implementaciji Alvina ili skladišta podataka nije ništa nečuveno. U prvom eksperimentu dobivamo sljedeći graf:
Kao što vidite, nema poboljšanja pri korištenju ping-ping poslužitelja. To znači da skladište podataka ne povećava latenciju, a popis sumnjivih je prepolovljen:
- Mrežni poziv od klijenta do Alvina.
- Mrežni poziv od Alvina klijentu.
Sjajno! Popis se brzo smanjuje. Mislio sam da sam skoro shvatio razlog.
gRPC
Sada je vrijeme da vam predstavimo novog igrača: gRPC
dobro optimiziran i široko korišten, ovo je bio moj prvi put da ga koristim na sustavu ove veličine i očekivao sam da će moja implementacija biti ispod optimalne - u najmanju ruku.
Dostupnost gRPC
u hrpi potaknuo je novo pitanje: možda je to moja implementacija ili ja gRPC
uzrokuje problem kašnjenja? Dodavanje novog osumnjičenika na popis:
- Klijent zove knjižnicu
gRPC
- knjižnica
gRPC
upućuje mrežni poziv knjižnici na klijentugRPC
na poslužitelju - knjižnica
gRPC
kontakti Alvin (nema rada u slučaju ping-pong poslužitelja)
Da vam dam predodžbu o tome kako kod izgleda, moja implementacija klijent/Alvin nije puno drugačija od one klijent-poslužitelj
Napomena: gornji popis je malo pojednostavljen jer
gRPC
omogućuje korištenje vlastitog (predloška?) modela niti, u kojem je stog izvršenja isprepletengRPC
i korisnička implementacija. Radi jednostavnosti, zadržat ćemo se na ovom modelu.
Profiliranje će sve popraviti
Nakon što sam prekrižio pohranu podataka, mislio sam da sam skoro gotov: “Sada je lako! Primijenimo profil i saznajmo gdje dolazi do kašnjenja.” ja
Uzeo sam četiri profila: s visokim QPS-om (niska latencija) i s ping-pong serverom s niskim QPS-om (visoka latencija), i na strani klijenta i na strani servera. I za svaki slučaj, uzeo sam i ogledni profil procesora. Kad uspoređujem profile, obično tražim nenormalan skup poziva. Na primjer, loša strana s visokom latencijom je mnogo više promjena konteksta (10 puta ili više). Ali u mom slučaju, broj promjena konteksta bio je gotovo isti. Na moj užas, tu nije bilo ničeg značajnog.
Dodatno otklanjanje pogrešaka
Bila sam očajna. Nisam znao koje bih druge alate mogao upotrijebiti, a moj sljedeći plan bio je u biti ponoviti eksperimente s različitim varijacijama, a ne jasno dijagnosticirati problem.
Što ako
Od samog početka sam bio zabrinut zbog kašnjenja od 50 ms. Ovo je jako veliko vrijeme. Odlučio sam da ću izrezati dijelove koda dok ne otkrijem točno koji dio uzrokuje ovu pogrešku. Zatim je uslijedio eksperiment koji je upalio.
Kao i obično, gledajući unatrag, čini se da je sve bilo očito. Postavio sam klijenta na isti stroj kao i Alvin - i poslao zahtjev na localhost
. I povećanje latencije je nestalo!
Nešto nije bilo u redu s mrežom.
Učenje vještina mrežnog inženjera
Moram priznati: moje znanje o mrežnim tehnologijama je grozno, pogotovo s obzirom na to da s njima radim svaki dan. Ali mreža je bila glavni osumnjičeni i morao sam naučiti kako otkloniti pogreške.
Srećom, Internet voli one koji žele učiti. Kombinacija pinga i tracerta činila se kao dovoljno dobar početak za otklanjanje grešaka u problemima mrežnog prijenosa.
Prvo sam pokrenuo
Onda sam pokušao
Dakle, kašnjenje nije uzrokovao moj kod, gRPC implementacija ili mreža. Počeo sam se brinuti da to nikad neću razumjeti.
Sada na kojem smo OS-u
gRPC
široko korišten na Linuxu, ali egzotičan na Windowsima. Odlučio sam isprobati eksperiment koji je uspio: stvorio sam Linux virtualni stroj, kompajlirao Alvin za Linux i implementirao ga.
I evo što se dogodilo: Linux poslužitelj za ping-pong nije imao ista kašnjenja kao sličan Windows host, iako izvor podataka nije bio drugačiji. Ispostavilo se da je problem u gRPC implementaciji za Windows.
Nagleov algoritam
Sve ovo vrijeme mislio sam da mi nedostaje zastava gRPC
. Sada razumijem što je zapravo gRPC
Windows zastavica nedostaje. Pronašao sam internu RPC biblioteku za koju sam bio uvjeren da će dobro funkcionirati za sve postavljene oznake
skoro Gotovo: počeo sam uklanjati dodane oznake jednu po jednu dok se regresija nije vratila kako bih mogao točno odrediti uzrok. Bilo je zloglasno
gRPC
ova je zastavica postavljena u implementaciji Linuxa za TCP utičnice, ali ne i u Windowsima. Ja sam ovo
Zaključak
Veća latencija pri niskom QPS-u uzrokovana je optimizacijom OS-a. Retrospektivno, profiliranje nije otkrilo latenciju jer je učinjeno u načinu kernela, a ne u
Što se tiče eksperimenta s lokalnim hostom, vjerojatno nije dotaknuo stvarni mrežni kod i Nagleov algoritam se nije pokrenuo, pa su problemi s kašnjenjem nestali kada je klijent došao do Alvina preko lokalnog hosta.
Sljedeći put kad vidite povećanje latencije kako se smanjuje broj zahtjeva u sekundi, Nagleov algoritam bi trebao biti na vašem popisu sumnjivih!
Izvor: www.habr.com