Bioyino - grumbullues i metrikës i shpërndarë, i shkallëzuar

Kështu që ju mblidhni metrikë. Siç jemi ne. Ne gjithashtu mbledhim metrikë. Sigurisht, e nevojshme për biznes. Sot do të flasim për lidhjen e parë të sistemit tonë të monitorimit - një server grumbullimi i pajtueshëm me statsd bioyino, pse e kemi shkruar dhe pse e kemi braktisur brubekin.

Bioyino - grumbullues i metrikës i shpërndarë, i shkallëzuar

Nga artikujt tanë të mëparshëm (1, 2) mund të zbuloni se deri në ca kohë kemi mbledhur nota duke përdorur Brubeck. Është shkruar në C. Nga pikëpamja e kodit, është po aq e thjeshtë sa një prizë (kjo është e rëndësishme kur doni të kontribuoni) dhe, më e rëndësishmja, ai trajton vëllimet tona prej 2 milion metrikë për sekondë (MPS) në kulmin pa asnjë problem. Në dokumentacion thuhet mbështetje për 4 milionë MPS me yll. Kjo do të thotë që ju do të merrni shifrën e deklaruar nëse e konfiguroni saktë rrjetin në Linux. (Nuk e dimë sa MPS mund të merrni nëse e lini rrjetin siç është). Pavarësisht këtyre avantazheve, ne patëm disa ankesa serioze për brubeck.

Pretendimi 1. Github, zhvilluesi i projektit, pushoi së mbështeturi atë: publikimi i arnimeve dhe rregullimeve, pranimi i PR-së tonë dhe (jo vetëm tonën). Muajt ​​e fundit (diku nga shkurt-mars 2018) ka rinisur aktiviteti, por para kësaj ka pasur gati 2 vite qetësi të plotë. Përveç kësaj, projekti është duke u zhvilluar për nevojat e brendshme të Gihubit, e cila mund të bëhet një pengesë serioze për futjen e veçorive të reja.

Pretendimi 2. Saktësia e llogaritjeve. Brubeck mbledh gjithsej 65536 vlera për grumbullim. Në rastin tonë, për disa metrikë, gjatë periudhës së grumbullimit (30 sekonda), mund të arrijnë shumë më tepër vlera (1 në kulmin). Si rezultat i këtij kampionimi, vlerat maksimale dhe minimale duken të padobishme. Për shembull, si kjo:

Bioyino - grumbullues i metrikës i shpërndarë, i shkallëzuar
Siç ishte

Bioyino - grumbullues i metrikës i shpërndarë, i shkallëzuar
Si duhet të ishte

Për të njëjtën arsye, shumat përgjithësisht llogariten gabimisht. Shto këtu një defekt me një tejmbushje float 32-bit, e cila në përgjithësi e dërgon serverin në segfault kur merr një metrikë në dukje të pafajshme dhe gjithçka bëhet e mrekullueshme. Meqë ra fjala, defekti nuk është rregulluar.

Dhe, së fundi, Pretendimi X. Në momentin e shkrimit, ne jemi gati t'ua prezantojmë atë të 14 zbatimeve pak a shumë të statsd-së që kemi mundur të gjejmë. Le të imagjinojmë se një infrastrukturë e vetme është rritur aq shumë sa të pranosh 4 milionë MPS nuk mjafton më. Ose edhe nëse nuk është rritur ende, por metrikat janë tashmë aq të rëndësishme për ju, sa edhe uljet e shkurtra 2-3 minuta në grafikët mund të bëhen tashmë kritike dhe të shkaktojnë periudha depresioni të pakapërcyeshëm midis menaxherëve. Meqenëse trajtimi i depresionit është një detyrë e pafalshme, nevojiten zgjidhje teknike.

Së pari, toleranca ndaj gabimeve, në mënyrë që një problem i papritur në server të mos shkaktojë një apokalips psikiatrik zombie në zyrë. Së dyti, shkallëzimi për të qenë në gjendje të pranojë më shumë se 4 milionë MPS, pa u gërmuar thellë në grumbullin e rrjetit Linux dhe pa u rritur me qetësi "në gjerësi" në madhësinë e kërkuar.

Meqenëse kishim hapësirë ​​për shkallëzim, vendosëm të fillonim me tolerancën e gabimeve. "RRETH! Toleranca ndaj gabimeve! Është e thjeshtë, ne mund ta bëjmë atë," menduam dhe lançuam 2 serverë, duke ngritur një kopje të brubeck në secilin. Për ta bërë këtë, na u desh të kopjonim trafikun me metrikë në të dy serverët dhe madje të shkruanim për këtë dobi të vogël. Ne e zgjidhëm problemin e tolerancës së gabimeve me këtë, por... jo shumë mirë. Në fillim gjithçka dukej e shkëlqyeshme: çdo brubeck mbledh versionin e vet të grumbullimit, shkruan të dhëna në Graphite një herë në 30 sekonda, duke mbishkruar intervalin e vjetër (kjo bëhet në anën e Grafitit). Nëse një server dështon papritur, ne kemi gjithmonë një të dytë me kopjen e tij të të dhënave të grumbulluara. Por këtu është problemi: nëse serveri dështon, një "sharrë" shfaqet në grafikët. Kjo për faktin se intervalet prej 30 sekondash të brubeck nuk janë të sinkronizuara dhe në momentin e përplasjes njëra prej tyre nuk mbishkruhet. Kur fillon serveri i dytë, e njëjta gjë ndodh. Mjaft e tolerueshme, por dua më mirë! Problemi i shkallëzueshmërisë gjithashtu nuk është zhdukur. Të gjitha metrikat ende "fluturojnë" në një server të vetëm, dhe për këtë arsye ne jemi të kufizuar në të njëjtat 2-4 milion MPS, në varësi të nivelit të rrjetit.

Nëse mendoni pak për problemin dhe në të njëjtën kohë gërmoni borën me një lopatë, atëherë mund të vijë në mendje ideja e mëposhtme e qartë: keni nevojë për një statsd që mund të funksionojë në modalitetin e shpërndarë. Kjo do të thotë, ai që zbaton sinkronizimin midis nyjeve në kohë dhe metrikë. “Sigurisht, një zgjidhje e tillë ndoshta ekziston tashmë”, thamë dhe shkuam në Google…. Dhe ata nuk gjetën asgjë. Pasi kaloni dokumentacionin për statsd të ndryshme (https://github.com/etsy/statsd/wiki#server-implementations që nga 11.12.2017 dhjetori XNUMX), nuk gjetëm absolutisht asgjë. Me sa duket, as zhvilluesit dhe as përdoruesit e këtyre zgjidhjeve nuk kanë hasur ende kaq shumë metrika, përndryshe ata patjetër do të dilnin me diçka.

Dhe pastaj u kujtuam për "lodrën" statsd - bioyino, e cila u shkrua në hackathon Just for Fun (emri i projektit u krijua nga skenari para fillimit të hackathon) dhe kuptuam se ne kishim nevojë urgjente për statsd-në tonë. Per cfare?

  • sepse ka shumë pak klone statsd në botë,
  • sepse është e mundur të sigurohet toleranca e dëshiruar ose afër tolerancës dhe shkallëzimit të defektit (përfshirë sinkronizimin e metrikave të grumbulluara midis serverëve dhe zgjidhjen e problemit të dërgimit të konflikteve),
  • sepse është e mundur të llogariten metrikat më saktë se sa bën Brubeck,
  • sepse ju mund të mblidhni statistika më të detajuara vetë, të cilat brubeck praktikisht nuk na i dha,
  • sepse pata mundësinë të programoja aplikacionin tim të laboratorit të shkallës së shpërndarë me hiperperformancë, i cili nuk do të përsërisë plotësisht arkitekturën e një hiper tjetër të ngjashëm... mirë, kjo është ajo.

mbi çfarë të shkruani? Sigurisht, në Rust. Pse?

  • sepse kishte tashmë një zgjidhje prototip,
  • sepse autori i artikullit tashmë e njihte Rust në atë kohë dhe ishte i etur të shkruante diçka në të për prodhim me mundësinë për ta vendosur atë në burim të hapur,
  • sepse gjuhët me GC nuk janë të përshtatshme për ne për shkak të natyrës së trafikut të marrë (pothuajse në kohë reale) dhe pauzat e GC janë praktikisht të papranueshme,
  • sepse keni nevojë për performancë maksimale të krahasueshme me C
  • sepse Rust na siguron njëkohshmëri të patrembur dhe nëse do të fillonim ta shkruanim në C/C++, do të kishim grumbulluar edhe më shumë dobësi, tejmbushje buferi, kushte gare dhe fjalë të tjera të frikshme sesa brubeck.

Kishte edhe një argument kundër Rustit. Kompania nuk kishte përvojë në krijimin e projekteve në Rust, dhe tani ne gjithashtu nuk planifikojmë ta përdorim atë në projektin kryesor. Prandaj, kishte frikë serioze se asgjë nuk do të funksiononte, por vendosëm të shfrytëzonim një shans dhe u përpoqëm.

Koha kaloi...

Më në fund, pas disa përpjekjeve të dështuara, versioni i parë i punës ishte gati. Cfare ndodhi? Kjo është ajo që ndodhi.

Bioyino - grumbullues i metrikës i shpërndarë, i shkallëzuar

Çdo nyje merr grupin e vet të metrikave dhe i grumbullon ato, dhe nuk grumbullon metrikë për ato lloje ku grupi i tyre i plotë kërkohet për grumbullimin përfundimtar. Nyjet janë të lidhura me njëra-tjetrën nga një lloj protokolli i bllokimit të shpërndarë, i cili ju lejon të zgjidhni midis tyre të vetmin (këtu kemi qarë) që është i denjë për të dërguar metrikë tek i Madhi. Ky problem aktualisht po zgjidhet nga konsull, por në të ardhmen ambiciet e autorit shtrihen në të vetat zbatimi Trap, ku më i denja do të jetë, natyrisht, nyja e liderit të konsensusit. Përveç konsensusit, nyjet mjaft shpesh (një herë në sekondë si parazgjedhje) u dërgojnë fqinjëve të tyre ato pjesë të matjeve të para-agreguara që ata arritën të mbledhin në atë sekondë. Rezulton se shkallëzimi dhe toleranca ndaj gabimeve ruhen - çdo nyje ende mban një grup të plotë metrikash, por metrikat dërgohen tashmë të grumbulluara, nëpërmjet TCP dhe kodohen në një protokoll binar, kështu që kostot e dyfishimit reduktohen ndjeshëm në krahasim me UDP. Pavarësisht nga numri mjaft i madh i metrikave hyrëse, akumulimi kërkon shumë pak memorie dhe akoma më pak CPU. Për meritat tona shumë të kompresueshme, kjo është vetëm disa dhjetëra megabajt të dhëna. Si një bonus shtesë, nuk marrim rishkrime të panevojshme të të dhënave në Graphite, siç ishte rasti me Burbeck.

Paketat UDP me metrikë janë të pabalancuara midis nyjeve në pajisjet e rrjetit përmes një Round Robin të thjeshtë. Sigurisht, pajisja e rrjetit nuk analizon përmbajtjen e paketave dhe për këtë arsye mund të tërheqë shumë më tepër se 4 milion pako në sekondë, për të mos përmendur metrikat për të cilat nuk di fare. Nëse marrim parasysh që metrikat nuk vijnë një nga një në çdo paketë, atëherë nuk parashikojmë ndonjë problem performancës në këtë vend. Nëse një server rrëzohet, pajisja e rrjetit shpejt (brenda 1-2 sekondave) e zbulon këtë fakt dhe heq serverin e dëmtuar nga rrotullimi. Si rezultat i kësaj, nyjet pasive (d.m.th., jo-lider) mund të ndizen dhe fiken praktikisht pa vërejtur tërheqje në grafikët. Maksimumi që humbasim është pjesë e matjeve që hynë në sekondën e fundit. Një humbje/fikje/ndërrim i papritur i një drejtuesi do të krijojë ende një anomali të vogël (intervali prej 30 sekondash është ende jashtë sinkronizimit), por nëse ka komunikim midis nyjeve, këto probleme mund të minimizohen, për shembull, duke dërguar paketa sinkronizimi .

Pak për strukturën e brendshme. Aplikimi është, natyrisht, me shumë fije, por arkitektura e filetimit është e ndryshme nga ajo e përdorur në brubeck. Fijet në brubeck janë të njëjta - secila prej tyre është përgjegjëse si për mbledhjen e informacionit ashtu edhe për grumbullimin. Në bioyino, punëtorët ndahen në dy grupe: ata që janë përgjegjës për rrjetin dhe ata që janë përgjegjës për grumbullimin. Kjo ndarje ju lejon të menaxhoni në mënyrë më fleksibël aplikacionin në varësi të llojit të matjeve: ku kërkohet grumbullim intensiv, mund të shtoni grumbullues, ku ka shumë trafik në rrjet, mund të shtoni numrin e flukseve të rrjetit. Për momentin, në serverët tanë ne punojmë në 8 rrjete dhe 4 flukse grumbullimi.

Pjesa e numërimit (përgjegjëse për grumbullimin) është mjaft e mërzitshme. Buferët e mbushur nga flukset e rrjetit shpërndahen midis flukseve të numërimit, ku më pas analizohen dhe grumbullohen. Me kërkesë, metrikat jepen për dërgim në nyje të tjera. E gjithë kjo, duke përfshirë dërgimin e të dhënave midis nyjeve dhe punën me Konsullin, kryhet në mënyrë asinkrone, duke ekzekutuar në kornizë tokyo.

Shumë më tepër probleme gjatë zhvillimit u shkaktuan nga pjesa e rrjetit përgjegjëse për marrjen e metrikës. Qëllimi kryesor i ndarjes së flukseve të rrjetit në entitete të veçanta ishte dëshira për të reduktuar kohën që kalon një rrjedhë. jo për të lexuar të dhënat nga priza. Opsionet që përdorin UDP asinkron dhe recvmsg të rregullt u zhdukën shpejt: i pari konsumon shumë CPU në hapësirën e përdoruesit për përpunimin e ngjarjeve, i dyti kërkon shumë ndërrime konteksti. Prandaj tani përdoret recvmmsg me bufera të mëdhenj (dhe tamponët, zotërinj oficerë, nuk janë asgjë për ju!). Mbështetja për UDP-në e rregullt rezervohet për rastet e lehta ku recvmmsg nuk nevojitet. Në modalitetin e shumë mesazheve, është e mundur të arrihet gjëja kryesore: në shumicën dërrmuese të kohës, filli i rrjetit mbledh radhën e OS - lexon të dhënat nga priza dhe i transferon ato në buferin e hapësirës së përdoruesit, vetëm herë pas here kalon në dhënien e buferit të mbushur në agreguesit. Radha në prizë praktikisht nuk grumbullohet, numri i paketave të rënë praktikisht nuk rritet.

Shënim

Në cilësimet e paracaktuara, madhësia e tamponit është caktuar të jetë mjaft e madhe. Nëse papritmas vendosni të provoni vetë serverin, mund të hasni në faktin që pas dërgimit të një numri të vogël metrikash, ato nuk do të mbërrijnë në Graphite, duke mbetur në buferin e rrjedhës së rrjetit. Për të punuar me një numër të vogël metrikë, duhet të vendosni madhësinë e bufsize dhe task-queue-size në vlera më të vogla në konfigurim.

Më në fund, disa tabela për adhuruesit e grafikëve.

Statistikat për numrin e matjeve hyrëse për çdo server: më shumë se 2 milion MPS.

Bioyino - grumbullues i metrikës i shpërndarë, i shkallëzuar

Çaktivizimi i një prej nyjeve dhe rishpërndarja e metrikës hyrëse.

Bioyino - grumbullues i metrikës i shpërndarë, i shkallëzuar

Statistikat mbi matjet në dalje: vetëm një nyje dërgon gjithmonë - shefi i bastisjes.

Bioyino - grumbullues i metrikës i shpërndarë, i shkallëzuar

Statistikat e funksionimit të secilës nyje, duke marrë parasysh gabimet në module të ndryshme të sistemit.

Bioyino - grumbullues i metrikës i shpërndarë, i shkallëzuar

Detajet e metrikës hyrëse (emrat metrikë janë të fshehur).

Bioyino - grumbullues i metrikës i shpërndarë, i shkallëzuar

Çfarë po planifikojmë të bëjmë me gjithë këtë në vijim? Natyrisht, shkruaj kod, dreq...! Projekti fillimisht ishte planifikuar të ishte me burim të hapur dhe do të mbetet i tillë gjatë gjithë jetës së tij. Planet tona të menjëhershme përfshijnë kalimin në versionin tonë të Raft, ndryshimin e protokollit të homologëve në një më të lëvizshëm, prezantimin e statistikave të brendshme shtesë, llojeve të reja të matjeve, korrigjimet e gabimeve dhe përmirësime të tjera.

Sigurisht, të gjithë janë të mirëpritur të ndihmojnë në zhvillimin e projektit: të krijojmë PR, Çështje, nëse është e mundur do të përgjigjemi, do të përmirësojmë, etj.

Me këtë u tha, kjo është e gjitha njerëz, blini elefantët tanë!



Burimi: www.habr.com

Shto një koment