Mint a
Egy nap egy elégedetlen e-mailre ébredtem az Alvinnal való hosszú késések miatt, amelyet a közeljövőben terveztünk elindítani. Pontosabban, az ügyfél a 99. percentilis késleltetést 50 ms körüli tartományban tapasztalta, ami jóval meghaladja a várakozási időkeretünket. Ez meglepő volt, mivel alaposan teszteltem a szolgáltatást, különösen a késleltetést illetően, ami gyakori panasz.
Mielőtt az Alvint teszteltem volna, sok kísérletet futtattam 40 10 lekérdezéssel másodpercenként (QPS), amelyek mindegyike 40 ms-nál kevesebb késleltetést mutatott. Kész voltam kijelenteni, hogy nem értek egyet az eredményeikkel. Ám ha még egyszer megnézem a levelet, valami újat vettem észre: nem teszteltem pontosan az általuk említett körülményeket, a QPS-jük jóval alacsonyabb volt, mint az enyém. Én 1 ezer QPS-en teszteltem, de ők csak XNUMX ezernél. Futtattam egy másik kísérletet, ezúttal alacsonyabb QPS-sel, hogy megnyugtassam őket.
Mióta blogolok erről, valószínűleg már rájöttél, hogy a számuk helyes. Újra és újra teszteltem a virtuális kliensemet, ugyanazzal az eredménnyel: az alacsony kérések száma nemcsak a késleltetést növeli, hanem a 10 ms-nál hosszabb késleltetésű kérések számát is. Más szóval, ha 40k QPS-nél körülbelül 50 kérés másodpercenként haladta meg az 50 ms-ot, akkor 1k QPS-nél másodpercenként 100 kérés volt 50 ms felett. Paradoxon!
A keresés szűkítése
Ha késleltetési problémával szembesül egy sok összetevőt tartalmazó elosztott rendszerben, az első lépés a gyanúsítottak rövid listájának létrehozása. Nézzünk egy kicsit mélyebbre Alvin építészetében:
Jó kiindulópont a befejezett I/O átmenetek listája (hálózati hívások/lemezkeresések stb.). Próbáljuk kitalálni, hol van a késés. A klienssel való nyilvánvaló I/O mellett Alvin egy további lépést tesz: hozzáfér az adattárhoz. Ez a tároló azonban ugyanabban a fürtben működik, mint az Alvin, így a késleltetésnek kisebbnek kell lennie, mint az ügyfélnél. Tehát a gyanúsítottak listája:
- Hálózati hívás az ügyféltől Alvin felé.
- Hálózati hívás Alvintól az adattárba.
- Keresés a lemezen az adattárban.
- Hálózati hívás az adattárházból Alvinhoz.
- Hálózati hívás Alvintól egy ügyfélhez.
Próbáljunk meg néhány pontot áthúzni.
Az adattárolásnak ehhez semmi köze
Az első dolgom az volt, hogy az Alvint ping-ping szerverré alakítottam, amely nem dolgozza fel a kéréseket. Amikor kérést kap, üres választ ad vissza. Ha a várakozási idő csökken, akkor az Alvin vagy az adattárház megvalósításának hibája nem hallatlan. Az első kísérletben a következő grafikont kapjuk:
Mint látható, a ping-ping szerver használatakor nincs javulás. Ez azt jelenti, hogy az adattárház nem növeli a késleltetést, és a gyanúsítottak listája felére csökken:
- Hálózati hívás az ügyféltől Alvin felé.
- Hálózati hívás Alvintól egy ügyfélhez.
Nagy! A lista gyorsan zsugorodik. Azt hittem, már majdnem rájöttem az okára.
gRPC
Itt az ideje, hogy bemutassunk egy új játékost: gRPC
jól optimalizált és széles körben használt, ez volt az első alkalom, hogy ekkora rendszeren használtam, és arra számítottam, hogy a megvalósításom enyhén szólva nem lesz optimális.
elérhetőség gRPC
a veremben egy új kérdés merült fel: talán az én megvalósításom vagy én magam gRPC
késleltetési problémát okoz? Új gyanúsított felvétele a listára:
- Az ügyfél felhívja a könyvtárat
gRPC
- könyvtár
gRPC
hálózati hívást kezdeményez a kliens könyvtárábagRPC
a szerveren - könyvtár
gRPC
kapcsolattartó Alvin (ping-pong szerver esetén nincs művelet)
Hogy képet adjunk arról, hogyan néz ki a kód, az én kliens/Alvin implementációm nem sokban különbözik a kliens-szervertől
Megjegyzés: A fenti lista kissé leegyszerűsített, mert
gRPC
lehetővé teszi a saját (sablon?) szálfűzési modell használatát, amelyben a végrehajtási verem összefonódikgRPC
és a felhasználói megvalósítás. Az egyszerűség kedvéért maradunk ennél a modellnél.
A profilozás mindent megold
Miután áthúztam az adattárakat, azt hittem, már majdnem kész vagyok: „Most már könnyű! Alkalmazzuk a profilt, és derítsük ki, hol van a késés.” én
Négy profilt választottam: magas QPS-sel (alacsony késleltetéssel) és egy ping-pong szerverrel alacsony QPS-sel (magas késleltetéssel), mind a kliens, mind a szerver oldalon. És minden esetre vettem egy minta processzorprofilt is. A profilok összehasonlításakor általában egy rendellenes hívási veremre figyelek. Például a magas késleltetésű rossz oldalon sokkal több környezeti kapcsoló van (10-szer vagy többször). De az én esetemben a kontextusváltások száma majdnem ugyanannyi volt. Rémületemre nem volt ott semmi jelentős.
További hibakeresés
kétségbeesett voltam. Nem tudtam, milyen egyéb eszközöket használhatok, és a következő tervem lényegében az volt, hogy megismételjem a kísérleteket különböző változatokkal, ahelyett, hogy egyértelműen diagnosztizálnám a problémát.
Mi van ha
Kezdettől fogva aggódtam a konkrét 50 ms-os késleltetés miatt. Ez egy nagyon nagy idő. Úgy döntöttem, hogy darabokat vágok ki a kódból, amíg ki nem találom, hogy pontosan melyik rész okozza ezt a hibát. Aztán jött egy kísérlet, ami bevált.
Mint általában, utólag úgy tűnik, minden nyilvánvaló volt. A klienst ugyanarra a gépre helyeztem, mint az Alvint – és elküldtem egy kérést localhost
. És a látencia növekedése elmúlt!
Valami nem stimmelt a hálózattal.
Hálózatmérnöki ismeretek elsajátítása
Be kell vallanom: a hálózati technológiákkal kapcsolatos tudásom borzasztó, főleg, ha figyelembe vesszük, hogy minden nap dolgozom velük. De a hálózat volt az elsődleges gyanúsított, és meg kellett tanulnom a hibakeresést.
Szerencsére az internet szereti a tanulni vágyókat. A ping és a tracert kombinációja elég jó kezdetnek tűnt a hálózati szállítási problémák hibakereséséhez.
Először is elindítottam
Aztán megpróbáltam
Tehát nem az én kódom, a gRPC implementáció vagy a hálózat okozta a késést. Kezdtem aggódni, hogy ezt soha nem fogom megérteni.
Most milyen operációs rendszert használunk
gRPC
széles körben használt Linuxon, de egzotikus Windowson. Úgy döntöttem, kipróbálok egy kísérletet, ami bevált: létrehoztam egy Linux virtuális gépet, lefordítottam az Alvint Linuxra, és telepítettem.
És a következő történt: a Linux ping-pong szerveren nem voltak olyan késések, mint egy hasonló Windows gazdagépen, bár az adatforrás nem különbözött egymástól. Kiderült, hogy a probléma a Windows gRPC megvalósításában van.
Nagle algoritmusa
Egész idő alatt azt hittem, hiányzik egy zászló gRPC
. Most már értem, mi is ez valójában gRPC
A Windows zászló hiányzik. Találtam egy belső RPC-könyvtárat, amelyről meg voltam győződve, hogy minden jelzőkészlethez jól fog működni
csaknem Kész: Elkezdtem egyenként eltávolítani a hozzáadott jelzőket, amíg a regresszió vissza nem tért, hogy pontosan meghatározhassam az okot. Hírhedt volt
gRPC
ez a jelző a TCP socketekhez való Linux-megvalósításban be van állítva, de a Windowsban nem. én vagyok ez
Következtetés
Az alacsony QPS melletti magasabb késleltetést az operációs rendszer optimalizálása okozta. Utólag visszatekintve a profilalkotás nem észlelte a késleltetést, mert kernel módban történt, nem pedig benne
Ami a localhost kísérletet illeti, valószínűleg nem érintette a tényleges hálózati kódot, és a Nagle algoritmusa nem futott, így a késleltetési problémák megszűntek, amikor a kliens a localhost-on keresztül elérte az Alvint.
A következő alkalommal, amikor a várakozási idő növekedését tapasztalja, ahogy a másodpercenkénti kérések száma csökken, a Nagle algoritmusának szerepelnie kell a gyanúsítottak listáján!
Forrás: will.com