Понекад је више мање. Када смањење оптерећења резултира повећањем латенције

Као у већина постова, постоји проблем са дистрибуираном услугом, назовимо ову услугу Алвин. Овог пута нисам сам открио проблем, обавестили су ме момци са стране клијента.

Једног дана сам се пробудио са незадовољним мејлом због дугих кашњења са Алвином, који смо планирали да покренемо у блиској будућности. Конкретно, клијент је искусио кашњење од 99. перцентила у региону од 50 мс, што је знатно изнад нашег буџета за кашњење. Ово је било изненађујуће јер сам опсежно тестирао услугу, посебно на кашњењу, што је уобичајена жалба.

Пре него што сам ставио Алвина на тестирање, спровео сам много експеримената са 40 хиљада упита у секунди (КПС), а сви су показали кашњење мање од 10 мс. Био сам спреман да изјавим да се не слажем са њиховим резултатима. Али погледавши још једном писмо, приметио сам нешто ново: нисам баш тестирао услове које су они поменули, њихов КПС је био много нижи од мог. Тестирао сам на 40к КПС, али они само на 1к. Извео сам још један експеримент, овог пута са нижим КПС-ом, само да их умирим.

Пошто пишем о овоме на блогу, вероватно сте већ схватили да су њихови бројеви тачни. Тестирао сам свог виртуелног клијента изнова и изнова са истим резултатом: мали број захтева не само да повећава кашњење, већ и повећава број захтева са кашњењем већим од 10 мс. Другим речима, ако је при 40к КПС било око 50 захтева у секунди изнад 50мс, онда је при 1к КПС било 100 захтева изнад 50мс сваке секунде. Парадокс!

Понекад је више мање. Када смањење оптерећења резултира повећањем латенције

Сужавање претраге

Када се суочите са проблемом кашњења у дистрибуираном систему са много компоненти, први корак је креирање кратке листе осумњичених. Хајде да копамо мало дубље у Алвинову архитектуру:

Понекад је више мање. Када смањење оптерећења резултира повећањем латенције

Добра полазна тачка је листа извршених И/О прелаза (мрежни позиви/претраживања диска, итд.). Хајде да покушамо да схватимо где је кашњење. Поред очигледног И/О са клијентом, Алвин предузима додатни корак: приступа складишту података. Међутим, ово складиште ради у истом кластеру као и Алвин, тако да би кашњење требало да буде мање него код клијента. Дакле, листа осумњичених:

  1. Мрежни позив од клијента до Алвина.
  2. Мрежни позив од Алвина ка складишту података.
  3. Претражите диск у складишту података.
  4. Мрежни позив из складишта података Алвину.
  5. Мрежни позив од Алвина клијенту.

Покушајмо да прецртамо неке тачке.

Чување података нема никакве везе са тим

Прво што сам урадио је да претворим Алвина у пинг-пинг сервер који не обрађује захтеве. Када прими захтев, враћа празан одговор. Ако се кашњење смањи, онда грешка у имплементацији Алвина или складишта података није ништа нечувено. У првом експерименту добијамо следећи графикон:

Понекад је више мање. Када смањење оптерећења резултира повећањем латенције

Као што видите, нема побољшања када користите пинг-пинг сервер. То значи да складиште података не повећава кашњење, а листа осумњичених је преполовљена:

  1. Мрежни позив од клијента до Алвина.
  2. Мрежни позив од Алвина клијенту.

Велики! Листа се брзо смањује. Мислио сам да сам скоро схватио разлог.

гРПЦ

Сада је време да вас упознамо са новим играчем: гРПЦ. Ово је библиотека отвореног кода од Гоогле-а за комуникацију у процесу РПЦ. Иако gRPC добро оптимизован и широко коришћен, ово је био мој први пут да га користим на систему ове величине и очекивао сам да моја имплементација буде подоптимална - у најмању руку.

доступност gRPC у стеку је довео до новог питања: можда је то моја имплементација или ја gRPC узрокује проблем кашњења? Додавање новог осумњиченог на листу:

  1. Клијент позива библиотеку gRPC
  2. библиотека gRPC упућује мрежни позив библиотеци на клијенту gRPC на серверу
  3. библиотека gRPC контактира Алвина (нема операције у случају пинг-понг сервера)

Да бих вам дао представу о томе како изгледа код, моја имплементација клијент/Алвин се не разликује много од клијент-сервер асинхронизовани примери.

Напомена: Горња листа је мало поједностављена јер gRPC омогућава коришћење сопственог (шаблона?) нитног модела, у којем је стек извршења испреплетен gRPC и имплементација корисника. Ради једноставности, задржаћемо се овог модела.

Профилисање ће све поправити

Пошто сам прецртао складишта података, мислио сам да сам скоро завршио: „Сада је лако! Хајде да применимо профил и сазнамо где долази до кашњења." И велики љубитељ прецизног профилисања, јер су процесори веома брзи и најчешће нису уско грло. Већина кашњења се дешава када процесор мора да заустави обраду да би урадио нешто друго. Прецизно ЦПУ профилисање чини управо то: тачно бележи све промене контекста и јасно ставља до знања где долази до кашњења.

Узео сам четири профила: са високим КПС-ом (мало кашњење) и са пинг-понг сервером са ниским КПС-ом (висока латенција), и на страни клијента и на страни сервера. И за сваки случај, узео сам и узорак профила процесора. Када упоређујем профиле, обично тражим аномалан стек позива. На пример, са лоше стране са великим кашњењем, постоји много више промена контекста (10 пута или више). Али у мом случају, број промена контекста је био скоро исти. На мој ужас, ту није било ништа значајно.

Додатно отклањање грешака

Био сам у очају. Нисам знао које друге алате могу да користим, а мој следећи план је у суштини био да поновим експерименте са различитим варијацијама уместо да јасно дијагностикујем проблем.

Шта ако

Био сам забринут због специфичног кашњења од 50 мс од почетка. Ово је веома велико време. Одлучио сам да исечем делове кода док не откријем тачно који део изазива ову грешку. Затим је дошао експеримент који је успео.

Као и обично, гледајући уназад, чини се да је све било очигледно. Поставио сам клијента на исту машину као и Алвин - и послао захтев localhost. И повећање латенције је нестало!

Понекад је више мање. Када смањење оптерећења резултира повећањем латенције

Нешто није у реду са мрежом.

Учење вештина мрежног инжењера

Морам признати: моје познавање мрежних технологија је ужасно, поготово ако се узме у обзир да свакодневно радим са њима. Али мрежа је била главни осумњичени и морао сам да научим како да је отклоним.

Срећом, интернет воли оне који желе да уче. Комбинација пинга и трацерта је изгледала као довољно добар почетак за отклањање грешака у мрежном транспорту.

Прво сам лансирао ПсПинг на Алвинов ТЦП порт. Користио сам подразумевана подешавања - ништа посебно. Од преко хиљаду пингова, ниједан није прешао 10мс, осим првог који се загрејао. Ово је у супротности са уоченим повећањем латенције од 50 мс на 99. перцентилу: тамо, на сваких 100 захтева, требало је да видимо око један захтев са кашњењем од 50 мс.

Онда сам покушао трацерт: Можда постоји проблем на једном од чворова дуж руте између Алвина и клијента. Али трагач се такође вратио празних руку.

Дакле, кашњење није био мој код, имплементација гРПЦ-а или мрежа. Почео сам да бринем да ово никада нећу разумети.

Сада на ком ОС-у смо

gRPC широко се користи на Линук-у, али егзотично на Виндовс-у. Одлучио сам да испробам експеримент, који је успео: направио сам Линук виртуелну машину, компајлирао Алвина за Линук и применио је.

Понекад је више мање. Када смањење оптерећења резултира повећањем латенције

И ево шта се догодило: Линук пинг-понг сервер није имао иста кашњења као сличан Виндовс хост, иако се извор података није разликовао. Испоставило се да је проблем у имплементацији гРПЦ-а за Виндовс.

Наглеов алгоритам

Све ово време сам мислио да ми недостаје застава gRPC. Сада разумем шта је то заиста gRPC Виндовс заставица недостаје. Нашао сам интерну РПЦ библиотеку за коју сам био уверен да ће добро функционисати за све постављене заставице Винсоцк. Затим сам додао све ове заставице у гРПЦ и поставио Алвина на Виндовс, на закрпљеном Виндовс пинг-понг серверу!

Понекад је више мање. Када смањење оптерећења резултира повећањем латенције

Скоро Готово: Почео сам да уклањам додане заставице једну по једну док се регресија не врати како бих могао тачно да одредим узрок. Било је неславно ТЦП_НОДЕЛАИ, Наглеов алгоритамски прекидач.

Наглеов алгоритам покушава да смањи број пакета послатих преко мреже одлагањем преноса порука све док величина пакета не пређе одређени број бајтова. Иако ово може бити лепо за просечног корисника, то је деструктивно за сервере у реалном времену јер ће ОС одложити неке поруке, узрокујући заостајање на ниском КПС-у. У gRPC ова заставица је постављена у Линук имплементацији за ТЦП утичнице, али не и у Виндовс-у. Ја сам ово исправљен.

Закључак

Веће кашњење при ниском КПС-у је узроковано оптимизацијом ОС-а. Ретроспективно, профилисање није открило кашњење јер је урађено у режиму кернела, а не у кориснички режим. Не знам да ли се Наглеов алгоритам може посматрати кроз ЕТВ снимке, али би било занимљиво.

Што се тиче експеримента са локалним хостом, он вероватно није дотакао стварни мрежни код и Наглеов алгоритам се није покренуо, тако да су проблеми са кашњењем нестали када је клијент дошао до Алвина преко локалног хоста.

Следећи пут када видите повећање латенције како се број захтева у секунди смањује, Наглеов алгоритам би требало да буде на вашој листи осумњичених!

Извор: ввв.хабр.цом

Додај коментар