Як і ў
Аднойчы я прачнуўся ад незадаволенага ліста з-за вялікіх затрымак у Элвіна, якога мы планавалі запусціць у бліжэйшы час. У прыватнасці, кліент сутыкнуўся з затрымкай 99-га працэнты ў раёне 50 мс, нашмат вышэй нашага бюджэту затрымкі. Гэта было дзіўна, бо я старанна тэсціраваў сэрвіс, асабліва на затрымкі, бо гэта прадмет частых скаргаў.
Перш чым аддаць Элвіна ў тэставанне, я правёў шмат эксперыментаў з 40 тыс. запытаў у секунду (QPS), усё паказалі затрымку менш за 10 мс. Я гатовы быў заявіць, што не згодзен з іх вынікамі. Але яшчэ раз зірнуўшы на ліст, я звярнуў увагу на нешта новае: я сапраўды не тэставаў умовы, якія яны згадалі, іх QPS быў нашмат ніжэй, чым мой. Я тэсціраваў на 40k QPS, а яны толькі на 1k. Я запусціў яшчэ адзін эксперымент, на гэты раз з больш нізкім QPS, проста каб улагодзіць іх.
Паколькі я пішу пра гэта ў блогу - верагодна, вы ўжо зразумелі: іх лічбы аказаліся правільнымі. Я правяраў свайго віртуальнага кліента зноў і зноў, усё з тым жа вынікам: нізкая колькасць запытаў не толькі павялічвае затрымку, але павялічвае колькасць запытаў з затрымкай больш за 10 мс. Іншымі словамі, калі на 40k QPS каля 50 запытаў у секунду перавышалі 50 мс, то на 1k QPS кожную секунду было 100 запытаў вышэй за 50 мс. Парадокс!
Звужаем круг пошуку
Сутыкнуўшыся з праблемай затрымкі ў размеркаванай сістэме са шматлікімі кампанентамі перш за ўсё трэба скласці кароткі спіс падазраваных. Капнём крыху глыбей у архітэктуру Элвіна:
Добрай адпраўной кропкай з'яўляецца спіс выкананых пераходаў уводу-высновы (сеткавыя выклікі/пошук па дыску і т. д.). Паспрабуем высветліць, дзе затрымка. Апроч відавочнага ўводу-вываду з кліентам, Элвін робіць дадатковы крок: ён звяртаецца да сховішча дадзеных. Аднак гэтае сховішча працуе ў адным кластары з Элвінам, таму там затрымка павінна быць менш, чым з кліентам. Такім чынам, спіс падазраваных:
- Сеткавы выклік ад кліента да Элвіна.
- Сеткавы выклік ад Элвіна да сховішча дадзеных.
- Пошук на дыску ў сховішчы дадзеных.
- Сеткавы выклік са сховішча дадзеных да Элвіна.
- Сеткавай выклік ад Элвіна да кліента.
Паспрабуем выкрасліць некаторыя пункты.
Сховішча дадзеных ні пры чым
Перш за ўсё я пераўтварыў Элвіна ў сервер ping-ping, які не апрацоўвае запыты. Атрымаўшы запыт, ён вяртае пусты адказ. Калі затрымка памяншаецца, то памылка ў рэалізацыі Элвіна або сховішчы дадзеных - нічога такога нечуванага. У першым эксперыменце атрымліваем такі графік:
Як бачым, пры выкарыстанні сервера ping-ping не назіраецца ніякіх паляпшэнняў. Гэта азначае, што сховішча дадзеных не павялічвае затрымку, а спіс падазраваных скарачаецца ўдвая:
- Сеткавы выклік ад кліента да Элвіна.
- Сеткавай выклік ад Элвіна да кліента.
Выдатна! Спіс хутка скарачаецца. Я думаў, што амаль высветліў прычыну.
gRPC
Цяпер самы час прадставіць вам новага гульца: gRPC
добра аптымізаваны і шырока выкарыстоўваецца, я першы раз выкарыстоўваў яго ў сістэме такога маштабу, і я чакаў, што мая рэалізацыя будзе неаптымальнай - мякка кажучы.
наяўнасць gRPC
у стэку спарадзіла новае пытанне: можа, гэта мая рэалізацыя ці сам gRPC
выклікае праблему затрымкі? Дадаем у спіс новага падазраванага:
- Кліент выклікае бібліятэку
gRPC
- Бібліятэка
gRPC
на кліенце выконвае сеткавы выклік бібліятэкіgRPC
на сэрвэры - Бібліятэка
gRPC
звяртаецца да Элвіна (аперацыі няма ў выпадку сервера ping-pong)
Каб вы разумелі, як выглядае код, мая рэалізацыя кліента/Элвіна не моцна адрозніваецца ад кліент-серверных
Заўвага: прыведзены вышэй спіс крыху спрошчаны, бо
gRPC
дае магчымасць выкарыстання ўласнай (шаблоннай?) струменевай мадэлі, у якой пераплятаюцца стэк выкананняgRPC
і рэалізацыя карыстальніка. Дзеля прастаты будзем прытрымлівацца гэтай мадэлі.
Прафіляванне ўсё выправіць
Выкрасліўшы сховішчы дадзеных, я падумаў, што амаль скончыў: «Цяпер лёгка! Ужыем профіль і даведаемся, дзе ўзнікае затрымка». Я
Я ўзяў чатыры профіля: пад высокім QPS (маленькая затрымка) і з ping-pong серверам на нізкім QPS (вялікая затрымка), як на боку кліента, так і на боку сервера. І проста на ўсялякі выпадак таксама ўзяў узор профіля працэсара. Пры параўнанні профіляў я звычайна шукаю анамальны стэк выклікаў. Напрыклад, на дрэнным баку з высокай затрымкай адбываецца значна больш пераключэнняў кантэксту (у 10 і больш разоў). Але ў маім выпадку колькасць пераключэнняў кантэксту практычна супадала. Да майго жаху, там не аказалася нічога істотнага.
Дадатковая адладка
Я быў у роспачы. Я не ведаў, якія яшчэ інструменты можна выкарыстоўваць, а мой наступны план складаўся па сутнасці ў паўтарэнні эксперыментаў з рознымі варыяцыямі, а не выразным дыягнаставанні праблемы.
Што, калі
З самага пачатку мяне турбавала пэўны час затрымкі 50 мс. Гэта вельмі вялікае час. Я вырашыў, што буду выразаць кавалкі з кода, пакуль не змагу высветліць дакладна, якая частка выклікае гэтую памылку. Затым рушыў услед эксперымент, які спрацаваў.
Як звычайна, заднім розумам здаецца, што ўсё было відавочна. Я змясціў кліента на адну машыну з Элвінам - і адправіў запыт у localhost
. І павелічэнне затрымкі знікла!
Нешта было не так з сеткай.
Асвойваем навыкі сеткавага інжынера
Павінен прызнацца: мае веды сеткавых тэхналогій жахлівыя, асабліва з улікам таго, што я з імі працую штодня. Але сетка была галоўным падазраваным, і мне трэба было навучыцца, як яе наладжваць.
На шчасце, інтэрнет любіць тых, хто хоча вучыцца. Спалучэнне ping і tracert здавалася дастаткова добрым пачаткам для адладкі праблем сеткавага транспарту.
Па-першае, я запусціў
Затым я паспрабаваў
Такім чынам, прычынай затрымкі быў не мой код, не рэалізацыя gRPC і ня сетка. Я пачаў ужо хвалявацца, што ніколі гэтага не разумею.
Цяпер, на якой АС мы знаходзімся
gRPC
шырока выкарыстоўваецца ў Linux, але для Windows гэта экзотыка. Я вырашыў правесці эксперымент, які спрацаваў: я стварыў віртуальную машыну Linux, скампіляваў Элвіна для Linux і разгарнуў яе.
І вось што атрымалася: у ping-pong серверы Linux не было такіх затрымак, як у аналагічнага вузла Windows, хоць крыніца дадзеных не адрознівалася. Аказваецца, праблема ў рэалізацыі gRPC для Windows.
Алгарытм Нейгла
Увесь гэты час я думаў, што мне не хапае сцяга gRPC
. Цяпер я зразумеў, што на самой справе гэта ў gRPC
не хапае сцяга Windows. Я знайшоў унутраную бібліятэку RPC, у якой быў упэўнены, што яна добра працуе для ўсіх усталяваных сцягоў.
амаль гатова: я пачаў выдаляць дададзеныя сцягі па адным, пакуль не вярнулася рэгрэсія, так што я змог дакладна вызначыць яе прычыну. Гэта быў сумна вядомы
gRPC
быў усталяваны гэты сцяг у рэалізацыі Linux для сокетаў TCP, але не для Windows. Я гэта
Заключэнне
Вялікую затрымку на нізкім QPS выклікала аптымізацыя АС. Азіраючыся назад, прафіляванне не выявіла затрымку, таму што праводзілася ў рэжыме ядра, а не ў
Што да эксперыменту localhost, ён, верагодна, не дакранаўся фактычнага сеткавага кода, і алгарытм Нейгла не запусціўся, таму праблемы з затрымкай зніклі, калі кліент звярнуўся да Элвіна праз localhost.
У наступны раз, калі ўбачыце павелічэнне затрымкі пры памяншэнні колькасці запытаў у секунду, алгарытм Нейгла павінен быць у вашым спісе падазраваных!
Крыніца: habr.com