Bioyino - en distribuerad, skalbar aggregator av metrik

SĂ„, ni samlar in mĂ€tvĂ€rden. Precis som vi. Vi samlar ocksĂ„ in mĂ€tvĂ€rden. SjĂ€lvklart sĂ„dana som Ă€r viktiga för affĂ€ren. Idag kommer vi att berĂ€tta om den första lĂ€nken i vĂ„rt övervakningssystem – en statsd-kompatibel aggregationsserver. bioyino, varför vi skrev den och varför vi övergav brubeck.

Bioyino - en distribuerad, skalbar aggregator av metrik

FrÄn vÄra tidigare artiklar (1, 2) kan man förstÄ att vi tills för en tid sedan samlade in etiketterna med hjÀlp av brubeck. Den Àr skriven i C. Ur kodens synvinkel Àr den enkel som en kork (detta Àr viktigt nÀr du vill bidra) och, viktigast av allt, klarar den utan större problem av vÄra volymer pÄ 2 miljoner mÀtvÀrden per sekund (MPS) i toppen. Dokumentationen pÄstÄr sig stödja 4 miljoner MPS med en asterisk. Det betyder att du kommer att fÄ den angivna siffran om du konfigurerar nÀtverket korrekt pÄ Linux. (Vi vet inte hur mÄnga MPS man fÄr om man lÀmnar nÀtverket som det Àr). Trots dessa fördelar hade vi flera allvarliga klagomÄl pÄ brubeck.

KlagomĂ„l 1. Github – projektets utvecklare – har slutat att stödja den: publicera patchar och fixar, ta emot vĂ„ra och (inte bara vĂ„ra) PR. Under de senaste mĂ„naderna (nĂ„gon gĂ„ng frĂ„n februari-mars 2018) har aktiviteten ökat igen, men före det var det nĂ€stan tvĂ„ Ă„r av total tystnad. Dessutom utvecklas projektet för Gihubs interna behov, vilket kan bli ett allvarligt hinder för att införa nya funktioner.

KlagomÄl 2. Noggrannheten i berÀkningarna. Brubeck samlar in endast 65536 vÀrden för aggregation. I vÄrt fall kan det komma mycket fler vÀrden under aggregationsperioden (30 sekunder) för vissa mÀtvÀrden (1 527 392 i toppen). Som ett resultat av sÄdan sampling verkar max- och minvÀrdena vara vÀrdelösa. Till exempel sÄ hÀr:

Bioyino - en distribuerad, skalbar aggregator av metrik
Som det var

Bioyino - en distribuerad, skalbar aggregator av metrik
SĂ„ som det borde ha varit

Av samma anledning rÀknas summor överhuvudtaget felaktigt. LÀgg till en bugg med överflöde av 32-bitars flyttal, som helt enkelt fÄr servern att krascha vid mottagande av en till synes oskyldig mÀtning, och det blir verkligen utmÀrkt. Buggen har för övrigt inte blivit ÄtgÀrdad.

Och slutligen, KlagomĂ„l X. Vid tidpunkten för artikelns skrivning Ă€r vi redo att presentationera alla 14 mer eller mindre fungerande implementationer av statsd, som vi kunnat hitta. LĂ„t oss förestĂ€lla oss att en viss avgrĂ€nsad infrastruktur har vuxit sĂ„ mycket att 4 miljoner MPS inte lĂ€ngre Ă€r tillrĂ€ckligt. Eller sĂ„ har den kanske Ă€nnu inte vuxit, men metrik för er Ă€r redan sĂ„ viktiga att Ă€ven korta, 2–3 minuters avbrott i graferna kan bli kritiska och orsaka okontrollerbar Ă„ngest hos cheferna. Eftersom behandling av Ă„ngest Ă€r en tacksam uppgift krĂ€vs tekniska lösningar.

För det första, redundans, sÄ att ett plötsligt problem pÄ servern inte utlöser en psykiatrisk zombieapokalyps pÄ kontoret. För det andra, skalbarhet, för att fÄ möjlighet att hantera mer Àn 4 miljoner MPS, utan att grÀva djupt i Linux nÀtverksstack och kunna vÀxa "brett" till önskad storlek.

Eftersom vi hade marginal för skalbarhet beslutade vi att börja med redundans. "Åh! Redundans! Det Ă€r enkelt, det kan vi", tĂ€nkte vi och startade 2 servrar, dĂ€r vi sĂ€tter upp en kopia av brubeck pĂ„ varje. För detta behövde vi kopiera trafiken med metrik till bĂ„da servrar och till och med skriva en liten verktygsprogram.. Redundansproblemet löste vi sĂ„, men... inte sĂ€rskilt bra. Först verkade allt vara bra: var och en brubeck samlar sin variant av aggregering, skriver data till Graphite var 30:e sekund, skrivandes över det gamla intervallet (detta görs pĂ„ Graphite-sidan). Om en server skulle fallera har vi alltid en andra med en egen kopia av de aggregerade data. Men hĂ€r Ă€r problemet: om en server fallerar uppstĂ„r en "sĂ„g" i graferna. Detta beror pĂ„ att 30-sekundersintervallen vid brubeck inte Ă€r synkroniserade, och i ögonblicket av ett fall registreras inte en av dem. Vid uppstart av den andra servern sker samma sak. Ganska acceptabelt, men vi vill ha bĂ€ttre! Problemet med skalbarhet försvann inte heller. Alla metrik fortsĂ€tter att "flyga" till en enda server, och dĂ€rför Ă€r vi begrĂ€nsade av de samma 2–4 miljoner MPS beroende pĂ„ nĂ€tverkskapaciteten.

Om man tĂ€nker lite pĂ„ problemet och samtidigt grĂ€ver snön med en spade, kan en sĂ„ uppenbar idĂ© dyka upp: vi behöver statsd som kan fungera i distribuerat lĂ€ge. Det vill sĂ€ga, ett som har synkronisering mellan noderna baserat pĂ„ tid och mĂ€tdata. "SjĂ€lvklart finns det sĂ€kert redan en sĂ„dan lösning", sa vi och började googla... och hittade ingenting. Efter att ha grĂ€vt igenom dokumentationen för olika statsd (https://github.com/etsy/statsd/wiki#server-implementations den 11.12.2017), hittade vi faktiskt ingenting. Tydligen har varken utvecklarna eller anvĂ€ndarna av dessa lösningar med SÅDANA mĂ€ngder mĂ€tningar stött pĂ„ det Ă€nnu, annars hade de sĂ€kert kommit pĂ„ nĂ„got.

Och hÀr kom vi ihÄg den "leksaks" statsd - bioyino, som vi skrev pÄ hackathonet just for fun (projektets namn genererade en script inför hackathonet) och insÄg att vi akut behövde vÄr egen statsd. Varför?

  • För att det finns för fĂ„ kloner av statsd i vĂ€rlden,
  • för att man kan sĂ€kerstĂ€lla önskad eller nĂ€rliggande tolerans mot fel och skalbarhet (inklusive synkronisering av aggregerade mĂ€tvĂ€rden mellan servrar och lösa problemet med konflikter vid sĂ€ndning),
  • för att man kan rĂ€kna mĂ€tningar mer exakt Ă€n vad brubeck gör,
  • för att vi kan samla in mer detaljerad statistik, vilket brubeck knappt gav oss,
  • för att vi fick chansen att programmera vĂ„r egen hyperperformance distributed scalable application, som inte kommer att helt Ă„terge arkitekturen av en annan sĂ„dan hyper... ni förstĂ„r.

Vad ska vi skriva pÄ? SjÀlvklart pÄ Rust. Varför?

  • för att det redan fanns en prototyp av lösningen,
  • för att artikelförfattaren vid den tidpunkten redan kĂ€nde till Rust och var sugen pĂ„ att skriva nĂ„got för produktion med möjlighet att publicera det som open-source,
  • för att sprĂ„k med GC inte passar oss pĂ„ grund av den typ av trafik vi fĂ„r (nĂ€stan realtime) och GC-pauser Ă€r nĂ€stan oacceptabla,
  • för att vi behöver maximal prestanda, jĂ€mförbar med C,
  • för att Rust erbjuder oss fearless concurrency, och om vi började skriva detta i C/C++, skulle vi fĂ„ Ă€nnu fler sĂ„rbarheter, buffertöverflöden, race conditions och andra skrĂ€mmande ord Ă€n vad brubeck redan har.

Det fanns ocksÄ ett argument mot Rust. Företaget hade ingen erfarenhet av att skapa projekt med Rust, och just nu planerar vi inte att anvÀnda det i huvudprojektet. DÀrför fanns det stora farhÄgor om att inget skulle fungera, men vi beslöt oss för att ta risken och pröva.

Tiden gick...

Till slut, efter flera misslyckade försök, var den första fungerande versionen klar. Vad fick vi? Vi fick nÄgot som detta.

Bioyino - en distribuerad, skalbar aggregator av metrik

Varje nod fĂ„r sin egen uppsĂ€ttning av metrik och samlar dem hos sig sjĂ€lv, utan att aggregera metriker för de typer dĂ€r full uppsĂ€ttning krĂ€vs för slutlig aggregering. Noderna Ă€r kopplade till varandra genom ett protokoll för distribuerad lĂ„sning (distributed lock), vilket gör det möjligt att vĂ€lja den enda (hĂ€r grĂ„ter vi), som Ă€r vĂ€rdig att skicka metrik till den Stora. Just nu löses detta problem med hjĂ€lp av Consul, men i framtiden strĂ€cker författarens ambitioner sig till en egen om implementering) Raft, dĂ€r den vĂ€rdiga Ă€r sjĂ€lvklart konsensusnodens ledare. Förutom konsensus skickar noder ofta (standard en gĂ„ng per sekund) delar av de föraggregerade metrikerna till sina grannar, som de lyckats samla under denna sekund. Resultatet Ă€r att skalbarhet och felresistens bevaras — varje nod hĂ„ller fortfarande en full uppsĂ€ttning metriker, men metrikerna skickas nu som aggregerade, över TCP och med kodning i ett binĂ€rt protokoll, vilket minskar kostnaderna för duplicering jĂ€mfört med UDP avsevĂ€rt. Trots det ganska stora antalet inkommande metriker krĂ€ver insamlingen mycket lite minne och Ă€nnu mindre CPU. För vĂ„ra vĂ€l komprimerade metriker handlar det om endast nĂ„gra tiotal megabyte data. Ytterligare en bonus Ă€r att vi slipper onödiga skrivningar av data i Graphite, som det var fallet med burbeck.

UDP-paket med mĂ€tningar Ă€r fördelade mellan noderna pĂ„ nĂ€tverksutrustningen genom en enkel Round Robin. Naturligtvis analyserar inte nĂ€tverksutrustningen innehĂ„llet i paketen och kan dĂ€rför hantera mycket mer Ă€n 4M paket per sekund, för att inte tala om mĂ€tningarna som den överhuvudtaget inte kĂ€nner till. Om man tar hĂ€nsyn till att mĂ€tningarna inte kommer en och en i varje paket, sĂ„ förutser vi inga prestandaproblem pĂ„ denna punkt. Vid serverkrasch upptĂ€cker nĂ€tverksutrustningen snabbt (inom 1-2 sekunder) detta och tar bort den kraschade servern frĂ„n rotationen. Som ett resultat av detta kan passiva (dvs. som inte Ă€r ledande) noder slĂ„s pĂ„ och av praktiskt taget utan att man mĂ€rker av nedgĂ„ngar pĂ„ graferna. Max, vad vi förlorar — Ă€r en del av mĂ€tningarna som kommit under den senaste sekunden. Plötslig förlust/avstĂ€ngning/byte av ledare kommer fortfarande att visa en liten anomali (30-sekundersintervallet Ă€r fortfarande desynkroniserat), men med kommunikation mellan noderna kan vi minimera dessa problem, till exempel genom att skicka synkroniserande paket.

Lite om den interna strukturen. Applikationen Ă€r naturligtvis flerdimensionell, men trĂ„dararkitekturen skiljer sig frĂ„n den som anvĂ€nds i brubeck. TrĂ„darna i brubeck Ă€r likartade — var och en ansvarar samtidigt för insamling av information och aggregering. I bioyino Ă€r arbetsströmmarna (workers) uppdelade i tvĂ„ grupper: de som ansvarar för nĂ€tverket och de som ansvarar för aggregering. Denna uppdelning gör det möjligt att hantera applikationen mer flexibelt beroende pĂ„ typ av mĂ€tningar: dĂ€r intensiv aggregering krĂ€vs kan vi lĂ€gga till fler aggregatorer, dĂ€r det Ă€r mycket nĂ€tverkstrafik — öka antalet nĂ€tverksströmmar. För nĂ€rvarande arbetar vi pĂ„ vĂ„ra servrar med 8 nĂ€tverks- och 4 aggregerande strömmar.

Den berÀkningsdel (ansvarig för aggregering) Àr ganska trÄkig. De fyllda buffertarna frÄn nÀtverksströmmarna fördelas mellan berÀkningsströmmarna, dÀr de sedan parsar och aggregerar. Vid förfrÄgan returneras mÀtningarna för skickning till andra noder. Allt detta, inklusive överföring av data mellan noderna och arbete med Consul, utförs asynkront, pÄ ett ramverk tokio.

Betydligt fler problem under utvecklingen orsakades av den nĂ€tverksdel som ansvarar för att ta emot mĂ€tvĂ€rden. Huvuduppgiften med att separera nĂ€tverksflöden i egna enheter var att minska den tid som flödet anvĂ€nder inte för att lĂ€sa data frĂ„n socket. Alternativen med asynkront UDP och vanligt recvmsg föll snabbt bort: den första anvĂ€nde för mycket CPU i user-space för hĂ€ndelsehantering, den andra — för mĂ„nga kontextbyten. DĂ€rför anvĂ€nds nu recvmmsg med stora buffertar (och buffrar, mina damer och herrar, Ă€r inte nĂ„got oviktigt!). Stöd för vanligt UDP har lĂ€mnats kvar för ot belastade fall dĂ€r det inte Ă€r nödvĂ€ndigt med recvmmsg. I multimeddelande-lĂ€get lyckas vi uppnĂ„ det viktigaste: majoriteten av tiden klarar nĂ€tverksflödet av att rensa operativsystemets kö — lĂ€ser data frĂ„n socket och flyttar dem till userspace-bufferten, bara sĂ€llan vĂ€xlar till att ge den fulla bufferten till aggregatörer. Kön i socket ansamlas praktiskt taget inte, antalet bortkastade paket ökar knappt.

AnmÀrkning

I standardinstÀllningarna Àr buffertstorleken tillrÀckligt stor. Om du av nÄgon anledning beslutar dig för att testa servern sjÀlv, kanske du stöter pÄ att efter att ha skickat en liten mÀngd mÀtvÀrden, kommer de inte att nÄ Graphite, utan stanna kvar i nÀtverksflödets buffert. För att hantera en liten mÀngd mÀtvÀrden behöver du stÀlla in bufsize och task-queue-size till mindre vÀrden i konfigurationsfilen.

Till sist — lite diagram för de som Ă€lskar diagram.

Statistik över antalet inkommande mÀtvÀrden per server: över 2 miljoner MPS.

Bioyino - en distribuerad, skalbar aggregator av metrik

StÀngning av en av noderna och omfördelning av inkommande mÀtvÀrden.

Bioyino - en distribuerad, skalbar aggregator av metrik

Statistik över utgĂ„ende mĂ€tvĂ€rden: endast en nod skickar alltid — raidbossen.

Bioyino - en distribuerad, skalbar aggregator av metrik

Statistik över varje nods arbete med hÀnsyn till fel i olika moduler i systemet.

Bioyino - en distribuerad, skalbar aggregator av metrik

Detaljerad information om inkommande mÀtvÀrden (namnen pÄ mÀtvÀrdena Àr dolda).

Bioyino - en distribuerad, skalbar aggregator av metrik

Vad planerar vi att göra med allt detta vidare? SjĂ€lvklart koda, bl
! Projektet var ursprungligen avsett att vara open-source och kommer att förbli sĂ„ under hela sin livstid. De nĂ€rmaste planerna inkluderar att gĂ„ över till vĂ„r egen version av Raft, byta peer-protokoll till ett mer portabelt, lĂ€gga till ytterligare intern statistik, nya typer av mĂ€tvĂ€rden, fixa buggar och andra förbĂ€ttringar.

SjÀlvklart Àr alla som vill hjÀlpa till att utveckla projektet vÀlkomna: skapa PR, Issues, och vi kommer att svara och förbÀttra nÀr vi kan, osv.

Och med det, som man sĂ€ger, that’s all folks, köp vĂ„ra elefanter!

Spela video


KĂ€lla: habr.com
Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster