Bioyino - verspreide, skaalbare metrieke aggregator

So jy samel metrieke in. Soos ons is. Ons samel ook metrieke in. Natuurlik nodig vir besigheid. Vandag sal ons praat oor die heel eerste skakel van ons moniteringstelsel - 'n statsd-versoenbare samevoegingsbediener bioyino, hoekom ons dit geskryf het en hoekom ons brubeck laat vaar het.

Bioyino - verspreide, skaalbare metrieke aggregator

Uit ons vorige artikels (1, 2) jy kan uitvind dat ons tot 'n geruime tyd punte ingesamel het met behulp van Brubeck. Dit is in C geskryf. Uit 'n kode-oogpunt is dit so eenvoudig soos 'n prop (dit is belangrik wanneer jy wil bydra) en, bowenal, dit hanteer ons volumes van 2 miljoen metrieke per sekonde (MPS) op 'n hoogtepunt sonder enige probleme. Die dokumentasie meld ondersteuning vir 4 miljoen MPS met 'n asterisk. Dit beteken dat jy die genoemde syfer sal kry as jy die netwerk korrek op Linux konfigureer. (Ons weet nie hoeveel MPS jy kan kry as jy die netwerk net so laat nie). Ten spyte van hierdie voordele het ons verskeie ernstige klagtes oor brubeck gehad.

Eis 1. Github, die ontwikkelaar van die projek, het opgehou om dit te ondersteun: plasings en regstellings publiseer, ons s'n en (nie net ons s'n nie) PR aanvaar. In die laaste paar maande (iewers vanaf Februarie-Maart 2018) het aktiwiteit hervat, maar voor dit was daar amper 2 jaar van volkome kalmte. Daarbenewens word die projek ontwikkel vir interne Gihub-behoeftes, wat 'n ernstige struikelblok vir die bekendstelling van nuwe funksies kan word.

Eis 2. Akkuraatheid van berekeninge. Brubeck versamel 'n totaal van 65536 waardes vir samevoeging. In ons geval, vir sommige statistieke, gedurende die samevoegingsperiode (30 sekondes), kan baie meer waardes aankom (1 op die hoogtepunt). As gevolg van hierdie steekproefneming lyk die maksimum en minimum waardes nutteloos. Byvoorbeeld, soos volg:

Bioyino - verspreide, skaalbare metrieke aggregator
Soos dit was

Bioyino - verspreide, skaalbare metrieke aggregator
Hoe dit moes gewees het

Om dieselfde rede word bedrae oor die algemeen verkeerd bereken. Voeg hier 'n fout by met 'n 32-bis-float-oorloop, wat die bediener oor die algemeen na 'n segfout stuur wanneer 'n oënskynlik onskuldige maatstaf ontvang word, en alles word wonderlik. Die fout, terloops, is nie reggemaak nie.

En laastens, Eis X. Met die skryf hiervan is ons gereed om dit aan al 14 min of meer werkende statistiese implementerings wat ons kon vind, aan te bied. Kom ons stel ons voor dat een of ander enkele infrastruktuur so gegroei het dat die aanvaarding van 4 miljoen MPS nie meer genoeg is nie. Of selfs al het dit nog nie gegroei nie, maar die maatstawwe is reeds vir jou so belangrik dat selfs kort, 2-3 minute dalings in die grafieke reeds kritiek kan word en aanvalle van onoorkomelike depressie onder bestuurders kan veroorsaak. Aangesien die behandeling van depressie 'n ondankbare taak is, is tegniese oplossings nodig.

Eerstens, foutverdraagsaamheid, sodat 'n skielike probleem op die bediener nie 'n psigiatriese zombie-apokalips in die kantoor veroorsaak nie. Tweedens, skaal om meer as 4 miljoen MPS te kan aanvaar, sonder om diep in die Linux-netwerkstapel te delf en rustig "in die breedte" te groei tot die vereiste grootte.

Aangesien ons ruimte gehad het vir skaal, het ons besluit om met foutverdraagsaamheid te begin. "OOR! Fout verdraagsaamheid! Dit is eenvoudig, ons kan dit doen,” het ons gedink en 2 bedieners geloods en 'n kopie van brubeck op elkeen opgestel. Om dit te doen, moes ons verkeer met statistieke na beide bedieners kopieer en selfs hiervoor skryf klein nut. Ons het die foutverdraagsaamheidsprobleem hiermee opgelos, maar ... nie baie goed nie. Aanvanklik het alles wonderlik gelyk: elke brubeck versamel sy eie weergawe van samevoeging, skryf data een keer elke 30 sekondes na Graphite, en skryf die ou interval oor (dit word aan die grafietkant gedoen). As een bediener skielik misluk, het ons altyd 'n tweede een met sy eie kopie van die saamgestelde data. Maar hier is die probleem: as die bediener misluk, verskyn 'n "saag" op die grafieke. Dit is te wyte aan die feit dat brubeck se 30-sekonde-intervalle nie gesinchroniseer is nie, en op die oomblik van 'n ongeluk word een daarvan nie oorgeskryf nie. Wanneer die tweede bediener begin, gebeur dieselfde ding. Nogal draaglik, maar ek wil beter hê! Die probleem van skaalbaarheid het ook nie verdwyn nie. Alle metrieke "vlieg" steeds na 'n enkele bediener, en daarom is ons beperk tot dieselfde 2-4 miljoen MPS, afhangende van die netwerkvlak.

As jy 'n bietjie oor die probleem dink en terselfdertyd sneeu met 'n graaf opgrawe, kan die volgende ooglopende idee by jou opkom: jy het 'n statsd nodig wat in verspreide modus kan werk. Dit wil sê, een wat sinchronisasie tussen nodusse in tyd en metrieke implementeer. "Natuurlik bestaan ​​so 'n oplossing waarskynlik reeds," het ons gesê en na Google gegaan .... En hulle het niks gevind nie. Nadat u deur die dokumentasie vir verskillende statistieke gegaan het (https://github.com/etsy/statsd/wiki#server-implementations vanaf 11.12.2017 Desember XNUMX), het ons absoluut niks gevind nie. Blykbaar het nóg die ontwikkelaars nóg die gebruikers van hierdie oplossings nog SO baie maatstawwe teëgekom, anders sou hulle beslis met iets vorendag kom.

En toe onthou ons van die "speelgoed" statsd - bioyino, wat geskryf is by die Just for Fun hackathon (die naam van die projek is deur die draaiboek gegenereer voor die begin van die hackathon) en besef dat ons ons eie statistieke dringend nodig het. Vir wat?

  • omdat daar te min statsd-klone in die wêreld is,
  • omdat dit moontlik is om die verlangde of naby aan die verlangde fouttoleransie en skaalbaarheid te verskaf (insluitend die sinchronisering van saamgestelde statistieke tussen bedieners en die oplossing van die probleem van stuurkonflik),
  • omdat dit moontlik is om metrieke meer akkuraat te bereken as wat Brubeck doen,
  • omdat u self meer gedetailleerde statistieke kan insamel, wat brubeck feitlik nie aan ons verskaf het nie,
  • want ek het 'n kans gehad om my eie hiperprestasie verspreide skaallabplication te programmeer, wat nie die argitektuur van 'n ander soortgelyke hiper heeltemal sal herhaal nie... wel, dit is dit.

Waarop om te skryf? Natuurlik in Rust. Hoekom?

  • omdat daar reeds 'n prototipe oplossing was,
  • omdat die skrywer van die artikel Rust op daardie stadium reeds geken het en gretig was om iets daarin te skryf vir produksie met die geleentheid om dit in oopbron te plaas,
  • omdat tale met GC nie vir ons geskik is nie as gevolg van die aard van die verkeer wat ontvang word (byna intydse) en GC-pouses feitlik onaanvaarbaar is,
  • want jy benodig maksimum werkverrigting vergelykbaar met C
  • want Rust voorsien ons van vreeslose sameloop, en as ons dit in C/C++ begin skryf het, sou ons nog meer kwesbaarhede, bufferoorlope, rastoestande en ander skrikwekkende woorde as brubeck ingehark het.

Daar was ook 'n argument teen Rust. Die maatskappy het geen ondervinding gehad om projekte in Rust te skep nie, en nou beplan ons ook nie om dit in die hoofprojek te gebruik nie. Daarom was daar ernstige vrese dat niks sou uitwerk nie, maar ons het besluit om 'n kans te waag en probeer.

Tyd het verbygegaan...

Uiteindelik, na verskeie mislukte pogings, was die eerste werkende weergawe gereed. Wat het gebeur? Dit is wat gebeur het.

Bioyino - verspreide, skaalbare metrieke aggregator

Elke nodus ontvang sy eie stel metrieke en versamel dit, en versamel nie maatstawwe vir daardie tipes waar hul volle stel nodig is vir finale samevoeging nie. Die nodusse is aan mekaar verbind deur 'n soort verspreide slotprotokol, wat jou toelaat om die enigste een (hier het ons gehuil) te kies wat waardig is om statistieke na die Grote te stuur. Hierdie probleem word tans opgelos deur konsul, maar in die toekoms strek die skrywer se ambisies tot eie implementering Raft, waar die mees waardige een natuurlik die konsensusleier-knooppunt sal wees. Benewens konsensus, stuur nodusse gereeld (een keer per sekonde by verstek) daardie dele van vooraf saamgestelde statistieke aan hul bure wat hulle daarin geslaag het om in daardie sekonde in te samel. Dit blyk dat skaal en fouttoleransie behoue ​​bly - elke nodus bevat steeds 'n volledige stel metrieke, maar die metrieke word reeds saamgevoeg, via TCP en geënkodeer in 'n binêre protokol, so dupliseringskoste word aansienlik verminder in vergelyking met UDP. Ten spyte van die redelike groot aantal inkomende statistieke, verg akkumulasie baie min geheue en selfs minder SVE. Vir ons hoogs saamdrukbare mertics is dit slegs 'n paar tientalle megagrepe data. As 'n bykomende bonus kry ons geen onnodige data-herskrywings in Graphite nie, soos die geval was met burbeck.

UDP-pakkies met statistieke is ongebalanseerd tussen nodusse op netwerktoerusting deur 'n eenvoudige Round Robin. Natuurlik ontleed die netwerkhardeware nie die inhoud van pakkies nie en kan dus baie meer as 4M pakkies per sekonde trek, om nie eens te praat van maatstawwe waaroor dit glad nie weet nie. As ons in ag neem dat die maatstawwe nie een op 'n slag in elke pakkie kom nie, dan voorsien ons geen prestasieprobleme op hierdie plek nie. As 'n bediener ineenstort, bespeur die netwerktoestel vinnig (binne 1-2 sekondes) hierdie feit en verwyder die bediener wat omgeval het van rotasie. As gevolg hiervan kan passiewe (d.w.s. nie-leier) nodusse prakties aan- en afgeskakel word sonder om aftrekkings op die kaarte op te let. Die maksimum wat ons verloor is deel van die maatstawwe wat op die laaste sekonde ingekom het. 'n Skielike verlies/afskakeling/omskakeling van 'n leier sal steeds 'n geringe afwyking skep (die 30 sekonde interval is steeds nie gesinkroniseer), maar as daar kommunikasie tussen nodusse is, kan hierdie probleme geminimaliseer word, byvoorbeeld deur sinchronisasiepakkies uit te stuur .

'n Bietjie oor die interne struktuur. Die toepassing is natuurlik multithreaded, maar die threading-argitektuur verskil van dié wat in brubeck gebruik word. Die drade in brubeck is dieselfde - elkeen van hulle is verantwoordelik vir beide inligtingversameling en samevoeging. In bioyino word werkers in twee groepe verdeel: diegene wat verantwoordelik is vir die netwerk en diegene wat verantwoordelik is vir samevoeging. Hierdie afdeling laat jou toe om die toepassing meer buigsaam te bestuur, afhangende van die tipe metrieke: waar intensiewe samevoeging vereis word, kan jy aggregators byvoeg, waar daar baie netwerkverkeer is, kan jy die aantal netwerkvloeie byvoeg. Op die oomblik werk ons ​​op ons bedieners in 8 netwerk- en 4 samevoegingsvloeie.

Die tel (verantwoordelik vir samevoeging) deel is nogal vervelig. Buffers wat deur netwerkvloei gevul word, word onder telstrome versprei, waar hulle vervolgens ontleed en saamgevoeg word. Op versoek word maatstawwe gegee om na ander nodusse te stuur. Dit alles, insluitend die stuur van data tussen nodusse en werk met Consul, word asynchroon uitgevoer en op die raamwerk uitgevoer tokio.

Baie meer probleme tydens ontwikkeling is veroorsaak deur die netwerkdeel wat verantwoordelik is vir die ontvangs van metrieke. Die hoofdoel om netwerkvloei in afsonderlike entiteite te skei, was die begeerte om die tyd wat 'n vloei spandeer, te verminder geen om data uit die sok te lees. Opsies wat asynchrone UDP en gereelde recvmsg gebruik, het vinnig verdwyn: die eerste verbruik te veel gebruikersspasie-SVE ​​vir gebeurtenisverwerking, die tweede vereis te veel konteksskakelaars. Daarom word dit nou gebruik recvmmsg met groot buffers (en buffers, here offisiere, is niks vir julle nie!). Ondersteuning vir gereelde UDP is gereserveer vir ligte gevalle waar recvmmsg nie nodig is nie. In multiboodskapmodus is dit moontlik om die belangrikste ding te bereik: die oorgrote meerderheid van die tyd, die netwerkdraad hark die OS-tou - lees data vanaf die sok en dra dit oor na die gebruikersspasiebuffer, en skakel net af en toe oor om die gevulde buffer te gee aggregators. Die tou in die sok akkumuleer feitlik nie, die aantal gedaalde pakkies groei feitlik nie.

Let daarop

In die verstekinstellings is die buffergrootte gestel om redelik groot te wees. As jy skielik besluit om die bediener self te probeer, kan jy die feit teëkom dat na die stuur van 'n klein aantal metrieke, hulle nie in Graphite sal aankom nie, wat in die netwerkstroombuffer oorbly. Om met 'n klein aantal maatstawwe te werk, moet jy bufsize en taak-tou-grootte op kleiner waardes in die konfigurasie stel.

Ten slotte, 'n paar kaarte vir kaartliefhebbers.

Statistieke oor die aantal inkomende maatstawwe vir elke bediener: meer as 2 miljoen MPS.

Bioyino - verspreide, skaalbare metrieke aggregator

Deaktiveer een van die nodusse en herverspreiding van inkomende maatstawwe.

Bioyino - verspreide, skaalbare metrieke aggregator

Statistiek oor uitgaande statistieke: slegs een nodus stuur altyd - die klopjagbaas.

Bioyino - verspreide, skaalbare metrieke aggregator

Statistiek van die werking van elke nodus, met inagneming van foute in verskeie stelselmodules.

Bioyino - verspreide, skaalbare metrieke aggregator

Besonderhede van inkomende maatstawwe (metriekname is versteek).

Bioyino - verspreide, skaalbare metrieke aggregator

Wat beplan ons om volgende met dit alles te doen? Natuurlik, skryf kode, damn...! Die projek was oorspronklik beplan om oopbron te wees en sal dit regdeur sy lewe bly. Ons onmiddellike planne sluit in die oorskakeling na ons eie weergawe van Raft, die verandering van die eweknie-protokol na 'n meer draagbare een, die bekendstelling van bykomende interne statistieke, nuwe soorte statistieke, foutoplossings en ander verbeterings.

Natuurlik is almal welkom om te help met die ontwikkeling van die projek: skep PR, Kwessies, indien moontlik sal ons reageer, verbeter, ens.

Met dit gesê, dit is alles mense, koop ons olifante!



Bron: will.com

Voeg 'n opmerking