Kartais daugiau yra mažiau. Mažinant apkrovą, didėja delsa

Kaip dauguma pranešimų, yra problema su paskirstyta paslauga, pavadinkime šią paslaugą Alvinu. Šį kartą problemos neaptikau pati, informavo vaikinai iš kliento pusės.

Vieną dieną pabudau nuo nepatenkinto el. laiško dėl ilgo delsimo su Alvinu, kurį planavome paleisti artimiausiu metu. Tiksliau, klientas patyrė 99 procentilio delsą maždaug 50 ms, o tai gerokai viršijo mūsų delsos biudžetą. Tai nustebino, nes plačiai išbandžiau paslaugą, ypač delsos, kuri yra dažnas skundas.

Prieš pradėdamas išbandyti Alviną, atlikau daug eksperimentų su 40 10 užklausų per sekundę (QPS), kurių delsa buvo mažesnė nei 40 ms. Buvau pasiruošęs pareikšti, kad nesutinku su jų rezultatais. Tačiau dar kartą pažvelgęs į laišką, pastebėjau kai ką naujo: tiksliai neišbandžiau jų paminėtų sąlygų, jų QPS buvo daug mažesnis nei mano. Aš išbandžiau 1 XNUMX QPS, bet jie tik XNUMX tūkst. Aš atlikau kitą eksperimentą, šį kartą su mažesniu QPS, kad tik juos nuraminčiau.

Kadangi rašau apie tai tinklaraštyje, tikriausiai jau supratote, kad jų skaičiai buvo teisingi. Aš išbandžiau savo virtualų klientą vėl ir vėl, o rezultatas buvo tas pats: mažas užklausų skaičius ne tik padidina delsą, bet ir padidina užklausų, kurių delsa yra didesnė nei 10 ms, skaičių. Kitaip tariant, jei esant 40k QPS maždaug 50 užklausų per sekundę viršijo 50 ms, tai esant 1k QPS, kas sekundę buvo 100 užklausų virš 50 ms. Paradoksas!

Kartais daugiau yra mažiau. Mažinant apkrovą, didėja delsa

Paieškos siaurinimas

Susidūrus su delsos problema paskirstytoje sistemoje, kurioje yra daug komponentų, pirmiausia reikia sudaryti trumpą įtariamųjų sąrašą. Pasigilinkime į Alvino architektūrą:

Kartais daugiau yra mažiau. Mažinant apkrovą, didėja delsa

Geras atspirties taškas yra užbaigtų įvesties/išvesties perėjimų sąrašas (tinklo skambučiai/disko paieškos ir kt.). Pabandykime išsiaiškinti, kur yra vėlavimas. Be akivaizdaus įvesties / išvesties su klientu, Alvinas imasi papildomo žingsnio: jis pasiekia duomenų saugyklą. Tačiau ši saugykla veikia tame pačiame klasteryje kaip ir Alvin, todėl delsa turėtų būti mažesnė nei kliento. Taigi, įtariamųjų sąrašas:

  1. Tinklo skambutis iš kliento Alvinui.
  2. Tinklo skambutis iš Alvino į duomenų saugyklą.
  3. Ieškokite diske duomenų saugykloje.
  4. Tinklo skambutis iš duomenų saugyklos į Alviną.
  5. Tinklo skambutis iš Alvino klientui.

Pabandykime perbraukti kai kuriuos dalykus.

Duomenų saugojimas neturi nieko bendra su tuo

Pirmas dalykas, kurį padariau, buvo konvertuoti Alviną į ping-ping serverį, kuris neapdoroja užklausų. Gavęs užklausą, jis pateikia tuščią atsakymą. Jei delsa sumažėja, Alvin arba duomenų saugyklos diegimo klaida yra nieko negirdėta. Pirmajame eksperimente gauname tokią diagramą:

Kartais daugiau yra mažiau. Mažinant apkrovą, didėja delsa

Kaip matote, naudojant ping-ping serverį patobulinimų nėra. Tai reiškia, kad duomenų saugykla nepadidina delsos, o įtariamųjų sąrašas sumažėja per pusę:

  1. Tinklo skambutis iš kliento Alvinui.
  2. Tinklo skambutis iš Alvino klientui.

Puiku! Sąrašas sparčiai mažėja. Maniau, kad beveik supratau priežastį.

grRPC

Dabar pats laikas supažindinti jus su nauju žaidėju: grRPC. Tai atvirojo kodo „Google“ biblioteka, skirta bendravimui proceso metu RSC. Nors gRPC gerai optimizuotas ir plačiai naudojamas, tai buvo mano pirmas kartas, kai jį naudojau tokio dydžio sistemoje ir tikėjausi, kad įgyvendinimas bus neoptimalus – švelniai tariant.

Prieinamumas gRPC krūvoje kilo naujas klausimas: gal tai mano įgyvendinimas ar aš pats gRPC sukelia delsos problemą? Į sąrašą įtraukiamas naujas įtariamasis:

  1. Klientas skambina į biblioteką gRPC
  2. biblioteka gRPC atlieka tinklo skambutį į kliento biblioteką gRPC serveryje
  3. biblioteka gRPC kreipiasi į Alviną (neveikia stalo teniso serverio atveju)

Чтобы вы понимали, как выглядит код, моя реализация клиента/Элвина не сильно отличается от клиент-серверных asinchroniniai pavyzdžiai.

Pastaba: aukščiau pateiktas sąrašas yra šiek tiek supaprastintas, nes gRPC leidžia naudoti savo (šablono?) gijų kūrimo modelį, kuriame susipina vykdymo krūva gRPC ir naudotojo įgyvendinimas. Paprastumo dėlei pasiliksime prie šio modelio.

Profiliavimas viską sutvarkys

Perbraukęs duomenų saugyklas, maniau, kad beveik baigiau: „Dabar tai paprasta! Taikykime profilį ir išsiaiškinkime, kur vėluojama. aš didelis precizinio profiliavimo gerbėjas, nes CPU yra labai greiti ir dažniausiai nėra kliūtis. Dauguma vėlavimų atsiranda, kai procesorius turi sustabdyti apdorojimą, kad galėtų atlikti ką nors kita. Tikslus procesoriaus profiliavimas būtent tai ir daro: jis tiksliai įrašo viską konteksto jungikliai ir aiškiai parodo, kur atsiranda vėlavimų.

Aš pasirinkau keturis profilius: su dideliu QPS (maža delsa) ir su stalo teniso serveriu su mažu QPS (didelė delsa) tiek kliento, tiek serverio pusėje. Ir tik tuo atveju paėmiau ir procesoriaus profilio pavyzdį. Lygindamas profilius dažniausiai ieškau anomalios skambučių krūvos. Pavyzdžiui, blogoje pusėje su dideliu delsimu yra daug daugiau konteksto jungiklių (10 ar daugiau kartų). Tačiau mano atveju konteksto jungiklių skaičius buvo beveik toks pat. Mano siaubui, nieko reikšmingo ten nebuvo.

Papildomas derinimas

Buvau beviltiška. Nežinojau, kokias kitas priemones galėčiau naudoti, o kitas mano planas buvo iš esmės pakartoti eksperimentus su skirtingais variantais, o ne aiškiai diagnozuoti problemą.

Kas, jeigu

Nuo pat pradžių buvau susirūpinęs dėl konkretaus 50 ms delsos. Tai labai didelis laikas. Nusprendžiau iškirpti kodo dalis, kol galėsiu tiksliai išsiaiškinti, kuri dalis sukėlė šią klaidą. Tada atėjo eksperimentas, kuris pavyko.

Kaip įprasta, pažvelgus atrodo, kad viskas buvo akivaizdu. Įdėjau klientą į tą patį įrenginį kaip ir Alvinas – ir nusiunčiau užklausą localhost. Ir vėlavimo padidėjimas dingo!

Kartais daugiau yra mažiau. Mažinant apkrovą, didėja delsa

Kažkas negerai tinkle.

Mokytis tinklo inžinieriaus įgūdžių

Prisipažinsiu: mano žinios apie tinklo technologijas yra siaubingos, ypač turint omenyje tai, kad su jomis dirbu kasdien. Tačiau tinklas buvo pagrindinis įtariamasis, ir man reikėjo išmokti jį derinti.

Laimei, internetas mėgsta tuos, kurie nori mokytis. Ping ir tracert derinys atrodė pakankamai gera pradžia tinklo transporto problemų derinimui.

Pirmiausia paleidau PsPing į Alvino TCP prievadą. Naudojau numatytuosius nustatymus – nieko ypatingo. Iš daugiau nei tūkstančio pingų nė vienas neviršijo 10 ms, išskyrus pirmąjį, skirtą apšilimui. Tai prieštarauja pastebėtam 50 ms delsos padidėjimui ties 99 procentiliu: ten kas 100 užklausų turėjome matyti maždaug vieną užklausą, kurios delsa yra 50 ms.

Tada pabandžiau tracert: Viename iš maršruto tarp Alvin ir kliento mazgų gali kilti problemų. Tačiau pėdsakas taip pat grįžo tuščiomis rankomis.

Taigi delsą sukėlė ne mano kodas, gRPC diegimas ar tinklas. Pradėjau nerimauti, kad niekada to nesuprasiu.

Kokią OS dabar naudojame

gRPC plačiai naudojamas Linux sistemoje, bet egzotiškas sistemoje Windows. Nusprendžiau išbandyti eksperimentą, kuris pavyko: sukūriau Linux virtualią mašiną, sukompiliavau Alvin for Linux ir įdiegiau.

Kartais daugiau yra mažiau. Mažinant apkrovą, didėja delsa

Ir štai kas atsitiko: „Linux“ stalo teniso serveris neturėjo tokių vėlavimų kaip panašus „Windows“ pagrindinis kompiuteris, nors duomenų šaltinis nesiskyrė. Paaiškėjo, kad problema yra „Windows“ skirto gRPC diegime.

Naglės algoritmas

Visą tą laiką maniau, kad man trūksta vėliavos gRPC. Dabar suprantu, kas tai yra iš tikrųjų gRPC Trūksta „Windows“ vėliavėlės. Radau vidinę RPC biblioteką, kuri, tikėjausi, gerai veiks su visomis vėliavėlėmis winsock. Tada visas šias vėliavėles pridėjau prie gRPC ir įdiegiau Alvin sistemoje Windows, pataisytame Windows stalo teniso serveryje!

Kartais daugiau yra mažiau. Mažinant apkrovą, didėja delsa

Beveik Atlikta: pradėjau po vieną šalinti pridėtas vėliavėles, kol grįžo regresija, kad galėčiau tiksliai nustatyti priežastį. Tai buvo liūdnai pagarsėjusi TCP_NODELAY, Nagle algoritmo jungiklis.

Naglės algoritmas bando sumažinti tinkle siunčiamų paketų skaičių atidedant pranešimų siuntimą, kol paketo dydis viršija tam tikrą baitų skaičių. Nors tai gali būti malonu paprastam vartotojui, realaus laiko serveriams tai kenkia, nes OS uždels kai kuriuos pranešimus, sukeldama žemo QPS vėlavimą. U gRPC ši vėliavėlė buvo nustatyta „Linux“ diegime TCP lizdams, bet ne „Windows“. Aš esu tai pataisyta.

išvada

Didesnę delsą esant žemam QPS sąlygojo OS optimizavimas. Žvelgiant atgal, profiliavimas neaptiko delsos, nes buvo atlikta branduolio režimu, o ne įjungus vartotojo režimas. Nežinau, ar Nagle algoritmą galima stebėti per ETW fiksavimus, bet būtų įdomu.

Kalbant apie localhost eksperimentą, jis tikriausiai nepalietė tikrojo tinklo kodo ir Nagle algoritmas neveikė, todėl delsos problemos išnyko, kai klientas pasiekė Alvin per localhost.

Kai kitą kartą pastebėsite padidėjusį delsą, nes užklausų per sekundę skaičius mažėja, Nagle algoritmas turėtų būti jūsų įtariamųjų sąraše!

Šaltinis: www.habr.com

Добавить комментарий