Такім чынам, вы збіраеце метрыкі. Як і мы. Мы таксама збіраем метрыкі. Вядома ж, патрэбны для бізнэсу. Сёння мы раскажам аб самым першым звяне сістэмы нашага маніторынгу — statsd-сумяшчальным серверы агрэгацыі.
З папярэдніх нашых артыкулаў (
Прэтэнзія 1. Github – распрацоўшчык праекта – перастаў яго падтрымліваць: публікаваць патчы і фіксы, прымаць нашы і (не толькі нашы) PR. У апошнія некалькі месяцаў (дзесьці з лютага-сакавіка 2018) актыўнасць аднавілася, але перад гэтым было амаль 2 гады поўнага зацішша. Акрамя таго, праект распрацоўваецца
Прэтэнзія 2. Дакладнасць вылічэнняў. Brubeck збірае для агрэгацыі за ўсё 65536 значэнняў. У нашым выпадку для некаторых метрык у перыяд агрэгацыі (30 сек) можа прыходзіць значна больш значэнняў (1 у піку). У выніку такога сэмплявання, значэнні максімумаў і мінімумаў выглядаюць бескарыснымі. Напрыклад, вось так:
як было
Як павінна было быць
Па той жа прычыне сумы ўвогуле лічацца некарэктна. Дадайце сюды баг з перапаўненнем 32-бітнага float, якое наогул адпраўляе сервер у segfault пры атрыманні з выгляду нявіннай метрыкі, і становіцца наогул выдатна. Баг, дарэчы, так і не выпраўлены.
І, нарэшце, Прэтэнзія X. На момант напісання артыкула мы гатовы прад'явіць яго ўсім 14 больш-менш працуючым рэалізацыям statsd, якія нам удалося знайсці. Давайце ўявім, што некаторая асобна ўзятая інфраструктура вырасла настолькі, што прымаць 4 млн MPS ужо недастаткова. Ці хай яшчэ не вырасла, але метрыкі для вас ужо важныя настолькі, што нават кароткія, 2-3 хвілінныя правалы на графіках ужо могуць стаць крытычнымі і выклікаць прыступы непераадольнай дэпрэсіі ў мэнэджараў. Так як лячэнне дэпрэсіі - справа няўдзячная, неабходны тэхнічныя рашэнні.
Па-першае, адмоваўстойлівасць, каб раптоўная праблема на серверы не задаволіла ў офісе псіхіятрычны зомбі апакаліпсіс. Па-другое, маштабаванне, каб атрымаць магчымасць прымаць больш за 4 млн MPS, пры гэтым не капаць углыб сеткавага стэка Linux і спакойна расці "ўшыркі" да патрэбных памераў.
Паколькі па маштабаванні запас у нас быў, мы вырашылі пачаць з адмоваўстойлівасці. «О! Адмаўстойлівасць! Гэта проста, гэта мы ўмеем», - падумалі мы і запусцілі 2 сервера, падняўшы на кожным копію brubeck. Для гэтага нам прыйшлося капіяваць трафік з метрыкамі на абодва сервера і нават напісаць для гэтага
Калі крыху падумаць аб праблеме і адначасова пакапаць рыдлёўкай снег, то ў галаву можа прыйсці такая відавочная ідэя: патрэбен statsd, які ўмее працаваць у размеркаваным рэжыме. Гэта значыць такі, у якім рэалізавана сінхранізацыя паміж нодамі па часе і метрыкам. "Вядома ж, такое рашэнне напэўна ўжо ёсць", – сказалі мы і пайшлі гугліць…. І нічога не знайшлі. Прашэрсціўшы дакументацыю па розных statsd (
І тут мы ўспомнілі пра «цацачны» statsd – bioyino, які пісалі на хакатоне just for fun (назва праекту згенераваў скрыпт перад пачаткам хакатона) і зразумелі, што нам тэрмінова патрэбен уласны statsd. Навошта?
- таму што ў свеце занадта мала клонаў statsd,
- таму што можна забяспечыць жаданую або блізкую да жаданай адмоваўстойлівасць і маштабаванасць (у тым ліку сінхранізаваць агрэгаваныя метрыкі паміж серверамі і вырашыць праблему канфліктаў пры адпраўцы),
- таму што можна лічыць метрыкі дакладней, чым гэта робіць brubeck,
- таму што можна самім збіраць больш дэталёвую статыстыку, якую brubeck нам практычна не падаваў,
- таму што прадаставіўся шанец запраграмаваць свой уласны хайперформансдыстрыб'ютэдскейлаблаплікейшэн, які не будзе цалкам паўтараць архітэктуру іншага такога ж хайперфор… нувыпонели.
На чым пісаць? Вядома ж, на Rust. Чаму?
- таму што ўжо быў прататып рашэння,
- таму што аўтар артыкула на той момант ужо ведаў Rust і імкнуўся напісаць на ім што-небудзь для прадакшэна з магчымасцю выкласці гэта ў open-source,
- таму што мовы з GC нам не падыходзяць у сілу прыроды атрымоўванага трафіку (практычна realtime) і GC-паўзы практычна недапушчальныя,
- таму што патрэбна максімальная прадукцыйнасць, параўнальная з C
- таму што Rust дае нам fearless concurrency, а пачаўшы пісаць гэта на C/C++, мы б агрэблі яшчэ больш, чым у brubeck, уразлівасцяў, перапаўненняў буфера, race conditions і іншых страшных слоў.
Быў і аргумент супраць Rust. У кампаніі не было досведу стварэння праектаў на Rust, і цяпер мы таксама не плануем выкарыстоўваць яго ў асноўным праекце. Таму былі сур'ёзныя асцярогі, што нічога не атрымаецца, але мы вырашылі рызыкнуць і паспрабавалі.
Ішоў час…
Нарэшце, пасля некалькіх няўдалых спроб, першая якая працуе версія была гатова. Што атрымалася? Атрымалася вось такое.
Кожная нода атрымлівае свой уласны набор метрык і назапашвае іх у сябе, прычым не агрэгуе метрыкі для тых тыпаў, дзе для фінальнай агрэгацыі запатрабуецца іх поўны набор. Ноды злучаныя паміж сабой некаторым пратаколам размеркаванай блакавання (distributed lock), які дазваляе абраць сярод іх тую адзіную (тут мы плакалі), якая варта адпраўляць метрыкі Вялікаму. У дадзены момант гэтая праблема вырашаецца сродкамі.
UDP-пакеты з метрыкамі разбалансаваць паміж нодамі на сеткавым абсталяванні праз просты Round Robin. Само сабой, сеткавая жалязяка не разбірае змесціва пакетаў і таму можа пацягнуць значна больш, чым 4M пакетаў у секунду, не кажучы ўжо пра метрыкі, пра якія яна наогул нічога не ведае. Калі ўлічыць, што метрыкі прыходзяць не па адной у кожным пакеце, то праблем з прадукцыйнасцю ў гэтым месцы мы не прадбачым. У выпадку падзення сервера сеткавая прылада хутка (на працягу 1-2 секунд) выяўляе гэты факт і прыбірае які ўпаў сервер з ратацыі. У выніку гэтага пасіўныя (г.зн. не якія з'яўляюцца лідэрам) ноды можна ўключаць і выключаць практычна не заўважаючы прасадак на графіках. Максімум, што мы губляем - гэта частка метрык, якія прыйшлі за апошнюю секунду. Раптоўная страта/выключэнне/пераключэнне лідэра па-ранейшаму намалюе нязначную анамалію (30-секундны інтэрвал па-ранейшаму рассінхранізаваны), але пры наяўнасці сувязі паміж нодамі можна звесці да мінімуму і гэтыя праблемы, напрыклад, шляхам рассылання сінхранізуючых пакетаў.
Трохі аб унутранай прыладзе. Прыкладанне, вядома ж, шматструменнае, але архітэктура патокаў адрозніваецца ад той, што выкарыстана ў brubeck. Струмені ў brubeck - аднолькавыя - кожны з іх адказвае адначасова і за збор інфармацыі, і за агрэгацыю. У bioyino працоўныя струмені (workers) падзеленыя на дзве групы: адказныя за сетку і адказныя за агрэгацыю. Такое падзел дазваляе больш гнутка кіраваць дадаткам у залежнасці ад тыпу метрык: там дзе патрабуецца інтэнсіўная агрэгацыя, можна дадаць агрэгатараў, там дзе шмат сеткавага трафіку - дадаць колькасць сеткавых патокаў. У дадзены момант на нашых серверах мы працуем у 8 сеткавых і 4 якія агрэгуюць струменя.
Якая лічыць (адказная за агрэгацыю) частка досыць сумная. Запоўненыя сеткавымі струменямі буферы размяркоўваюцца паміж якія лічаць патокамі, дзе ў далейшым парсяцца і агрэгуюцца. Па запыце метрыкі аддаюцца для адпраўкі на іншыя ноды. Усё гэта, уключаючы перасыланне дадзеных паміж нодамі і працу з Consul, выконваецца асінхронна, працуе на фрэймворку
Значна больш праблем пры распрацоўцы выклікала сеткавая частка, адказная за прыём метрык. Асноўнай задачай вылучэння сеткавых патокаў у асобныя сутнасці было імкненне паменшыць час, які паток затрачвае ня на чытанне дадзеных з сокета. Варыянты з выкарыстаннем асінхроннага UDP і звычайнага recvmsg хутка адпалі: першы есць занадта шмат user-space CPU на апрацоўку падзей, другі - занадта шмат пераключэнняў кантэксту. Таму зараз выкарыстоўваецца
Заўвага
У наладах па змаўчанні памер буфера выстаўлены дастаткова вялікім. Калі вы раптам вырашыце апрабаваць сервер самастойна, то, магчыма, сутыкнецеся з тым, што пасля адпраўкі маленькай колькасці метрык, яны не прыляцяць у Graphite, застаўшыся ў буферы сеткавага струменя. Для працы з невялікай колькасцю метрык трэба выставіць у канфігу bufsize і task-queue-size значэння паменш.
Напрыканцы - трохі графікаў для аматараў графікаў.
Статыстыка колькасці ўваходзяць метрык па кожным серверы: больш за 2 млн MPS.
Адключэнне адной з нод і пераразмеркаванне ўваходзячых метрык.
Статыстыка па выходных метрыках: адпраўляе заўсёды толькі адна нода - рэйдбос.
Статыстыка працы кожнай ноды з улікам памылак у розных модулях сістэмы.
Дэталізацыя ўваходзяць метрык (імёны метрык схаваны).
Што мы плануем з гэтым усім рабіць далей? Вядома ж пісаць код, бл…! Праект першапачаткова планаваўся як open-source і застанецца такім усё яго жыццё. У бліжэйшых планах – пераход на ўласную версію Raft, змена peer-пратакола на больш пераносны, унясенне дадатковай унутранай статыстыкі, новых тыпаў метрык, выпраўленне памылак і іншыя паляпшэнні.
Вядома ж, вітаюцца ўсе ахвочыя дапамагаць у развіцці праекта: стварайце PR, Issues, па магчымасці будзем адказваць, дапрацоўваць і г.д.
На гэтым, як той казаў, that's all folks, купляйце нашых сланоў!
Крыніца: habr.com