Bioyino - distribuita, skalebla metrika agregatoro

Do vi kolektas metrikojn. Kiel ni estas. Ni ankaŭ kolektas metrikojn. Kompreneble, necesa por komerco. Hodiaŭ ni parolos pri la unua ligilo de nia monitora sistemo - statsd-kongrua agrega servilo bioyino, kial ni skribis ĝin kaj kial ni forlasis brubeck.

Bioyino - distribuita, skalebla metrika agregatoro

El niaj antaŭaj artikoloj (1, 2) vi povas ekscii, ke ĝis kelka tempo ni kolektis markojn uzante Brubeck. Ĝi estas skribita en C. De koda vidpunkto, ĝi estas tiel simpla kiel ŝtopilo (ĉi tio gravas kiam vi volas kontribui) kaj, plej grave, ĝi pritraktas niajn volumojn de 2 milionoj da metrikoj por sekundo (MPS) ĉe pinto. sen problemoj. La dokumentaro deklaras subtenon por 4 milionoj da MPS kun asterisko. Ĉi tio signifas, ke vi ricevos la deklaritan ciferon se vi agordas la reton ĝuste en Linukso. (Ni ne scias kiom da MPS vi povas akiri se vi lasas la reton tia). Malgraŭ ĉi tiuj avantaĝoj, ni havis plurajn seriozajn plendojn pri brubeck.

Aserto 1. Github, la programisto de la projekto, ĉesis subteni ĝin: publikigi diakilojn kaj korektojn, akcepti nian kaj (ne nur nian) PR. En la lastaj monatoj (ie de februaro-marto 2018), la agado rekomenciĝis, sed antaŭ tio estis preskaŭ 2 jaroj da kompleta trankvilo. Krome, la projekto estas disvolvita por internaj bezonoj de Gihub, kiu povas fariĝi grava malhelpo al la enkonduko de novaj funkcioj.

Aserto 2. Precizeco de kalkuloj. Brubeck kolektas entute 65536 valorojn por agregado. En nia kazo, por iuj metrikoj, dum la agregacia periodo (30 sekundoj), multe pli da valoroj povas alveni (1 ĉe la pinto). Kiel rezulto de ĉi tiu specimeno, la maksimumaj kaj minimumaj valoroj ŝajnas senutilaj. Ekzemple, tiel:

Bioyino - distribuita, skalebla metrika agregatoro
Kiel ĝi estis

Bioyino - distribuita, skalebla metrika agregatoro
Kiel ĝi devus esti

Pro la sama kialo, kvantoj estas ĝenerale kalkulitaj malĝuste. Aldonu ĉi tie cimon kun 32-bita flosila superfluo, kiu ĝenerale sendas la servilon al segfault kiam ricevas ŝajne senkulpan metrikon, kaj ĉio fariĝas bonega. La cimo, cetere, ne estis riparita.

Kaj fine Aserto X. Dum la skribado, ni pretas prezenti ĝin al ĉiuj 14 pli-malpli laborantaj statsd-efektivigoj, kiujn ni povis trovi. Ni imagu, ke iu ununura infrastrukturo tiom kreskis, ke akcepti 4 milionojn da MPS ne plu sufiĉas. Aŭ eĉ se ĝi ankoraŭ ne kreskis, sed la metrikoj jam tiom gravas por vi, ke eĉ mallongaj, 2-3-minutaj trempoj en la leteroj povas jam fariĝi kritikaj kaj kaŭzi atakojn de nesuperebla depresio inter administrantoj. Ĉar trakti depresion estas sendanka tasko, necesas teknikaj solvoj.

Unue, faŭltoleremo, por ke subita problemo sur la servilo ne kaŭzu psikiatrian zombian apokalipso en la oficejo. Due, grimpi por povi akcepti pli ol 4 milionojn da MPS, sen fosi profunde en la Linuksan retan stakon kaj trankvile kreski "larĝe" al la bezonata grandeco.

Ĉar ni havis spacon por grimpi, ni decidis komenci kun misfunkciado. "PRI! Kulpo toleremo! Ĝi estas simpla, ni povas fari ĝin,” ni pensis kaj lanĉis 2 servilojn, levante kopion de brubeck sur ĉiu. Por fari tion, ni devis kopii trafikon kun metrikoj al ambaŭ serviloj kaj eĉ skribi por ĉi tio malgranda utileco. Ni solvis la problemon pri faŭltoleremo per ĉi tio, sed... ne tre bone. Komence ĉio ŝajnis bonega: ĉiu brubeck kolektas sian propran version de agregado, skribas datumojn al Grafito unufoje ĉiujn 30 sekundojn, anstataŭigante la malnovan intervalon (ĉi tio estas farita ĉe la flanko de Grafito). Se unu servilo subite malsukcesas, ni ĉiam havas duan kun sia propra kopio de la kunigitaj datumoj. Sed jen la problemo: se la servilo malsukcesas, "segilo" aperas sur la grafikaĵoj. Ĉi tio estas pro la fakto, ke la 30-sekundaj intervaloj de brubeck ne estas sinkronigitaj, kaj en la momento de kraŝo unu el ili ne estas anstataŭita. Kiam la dua servilo komenciĝas, okazas la sama afero. Tute tolerebla, sed mi volas pli bonan! La problemo de skaleblo ankaŭ ne malaperis. Ĉiuj metrikoj ankoraŭ "flugas" al ununura servilo, kaj tial ni estas limigitaj al la samaj 2-4 milionoj da MPS, depende de la retonivelo.

Se vi iomete pensas pri la problemo kaj samtempe elfosas neĝon per ŝovelilo, tiam eble venos en menso la jena evidenta ideo: vi bezonas statsd kiu povas funkcii en distribuita reĝimo. Tio estas, unu kiu efektivigas sinkronigon inter nodoj en tempo kaj metriko. "Kompreneble, tia solvo verŝajne jam ekzistas," ni diris kaj iris al Guglo... Kaj ili trovis nenion. Post ekzamenado de la dokumentado por malsamaj statistikoj (https://github.com/etsy/statsd/wiki#server-implementations ekde la 11.12.2017-a de decembro XNUMX), ni trovis absolute nenion. Ŝajne, nek la programistoj nek la uzantoj de ĉi tiuj solvoj ankoraŭ renkontis TIOM multajn metrikojn, alie ili certe elpensus ion.

Kaj tiam ni rememoris pri la "ludilo" statsd - bioyino, kiu estis skribita ĉe la Just for Fun hackathon (la nomo de la projekto estis generita de la skripto antaŭ la komenco de la hackathon) kaj rimarkis, ke ni urĝe bezonas nian propran statsd. Por kio?

  • ĉar estas tro malmultaj statsd-klonoj en la mondo,
  • ĉar estas eble disponigi la deziratan aŭ proksime al la dezirata faŭltoleremo kaj skaleblo (inkluzive de sinkronigado de agregitaj metrikoj inter serviloj kaj solvado de la problemo de sendado de konfliktoj),
  • ĉar eblas kalkuli metrikojn pli precize ol brubeck faras,
  • ĉar vi mem povas kolekti pli detalajn statistikojn, kiujn brubeck praktike ne disponigis al ni,
  • ĉar mi havis ŝancon programi mian propran hiperefikan distribuitskalan aplikadon, kiu ne tute ripetos la arkitekturon de alia simila hiperpor... nu, jen ĝi.

Sur kio skribi? Kompreneble, en Rusto. Kial?

  • ĉar jam ekzistis prototipa solvo,
  • ĉar la verkinto de la artikolo jam konis Rust tiutempe kaj fervoris skribi ion en ĝi por produktado kun la ŝanco meti ĝin en malfermfonte,
  • ĉar lingvoj kun GC ne taŭgas por ni pro la naturo de la ricevita trafiko (preskaŭ realtempa) kaj GC-paŭzoj estas praktike neakcepteblaj,
  • ĉar vi bezonas maksimuman rendimenton komparebla al C
  • ĉar Rusto provizas nin per sentima samtempeco, kaj se ni komencus skribi ĝin en C/C++, ni estus enirintaj eĉ pli da vundeblecoj, bufro-superfluoj, raskondiĉoj kaj aliaj timigaj vortoj ol brubeck.

Estis ankaŭ argumento kontraŭ Rust. La kompanio ne havis sperton pri kreado de projektoj en Rust, kaj nun ni ankaŭ ne planas uzi ĝin en la ĉefa projekto. Tial estis seriozaj timoj, ke nenio funkcios, sed ni decidis riski kaj provis.

La tempo pasis...

Fine, post pluraj malsukcesaj provoj, la unua funkcianta versio estis preta. Kio okazis? Jen kio okazis.

Bioyino - distribuita, skalebla metrika agregatoro

Ĉiu nodo ricevas sian propran aron de metriko kaj amasigas ilin, kaj ne agregas metrikon por tiuj tipoj kie ilia plena aro estas postulata por fina agregado. La nodoj estas konektitaj unu al la alia per ia distribua seruro-protokolo, kiu permesas elekti inter ili la solan (ĉi tie ni kriis), kiu indas sendi metrikojn al la Granda. Ĉi tiu problemo estas nuntempe solvita de konsulo, sed estonte la ambicioj de la aŭtoro etendiĝas al propra efektivigo Raft, kie la plej inda, kompreneble, estos la konsenta gvidanto nodo. Krom konsento, nodoj sufiĉe ofte (unufoje en sekundo defaŭlte) sendas al siaj najbaroj tiujn partojn de antaŭ-agregitaj metrikoj, kiujn ili sukcesis kolekti en tiu sekundo. Montriĝas, ke skalado kaj toleremo al misfunkciadoj estas konservitaj - ĉiu nodo ankoraŭ tenas plenan aron da metrikoj, sed la metrikoj estas senditaj jam kunigitaj, per TCP kaj koditaj en binaran protokolon, do duobligokostoj estas signife reduktitaj kompare kun UDP. Malgraŭ la sufiĉe granda nombro da envenantaj metrikoj, amasiĝo postulas tre malmulte da memoro kaj eĉ malpli CPU. Por niaj tre kunpremeblaj mertikoloj, ĉi tio estas nur kelkaj dekoj da megabajtoj da datumoj. Kiel kroma gratifiko, ni ricevas neniujn nenecesajn datumajn reverkojn en Grafito, kiel estis la kazo kun burbeck.

UDP-pakaĵetoj kun metriko estas malekvilibraj inter nodoj sur retaj ekipaĵoj per simpla Round Robin. Kompreneble, la reto aparataro ne analizas la enhavon de pakaĵoj kaj tial povas tiri multe pli ol 4M pakaĵetojn sekundo, sen mencii metrikojn pri kiuj ĝi scias tute nenion. Se ni konsideras, ke la metrikoj ne venas unuope en ĉiu pako, tiam ni ne antaŭvidas problemojn pri rendimento en ĉi tiu loko. Se servilo kraŝas, la reto-aparato rapide (en 1-2 sekundoj) detektas ĉi tiun fakton kaj forigas la kraŝintan servilon de rotacio. Kiel rezulto de tio, pasivaj (t.e., ne-gvidantoj) nodoj povas esti ŝaltitaj kaj malŝaltitaj praktike sen rimarki malaltiĝojn sur la furorlisto. La maksimumo, kiun ni perdas, estas parto de la metrikoj, kiuj venis en la lasta sekundo. Subita perdo/ĉesigo/ŝaltilo de gvidanto ankoraŭ kreos negravan anomalion (la 30-sekunda intervalo ankoraŭ estas malsinkronigita), sed se ekzistas komunikado inter nodoj, tiuj problemoj povas esti minimumigitaj, ekzemple, sendante sinkronigajn pakaĵetojn. .

Iom pri la interna strukturo. La aplikaĵo estas, kompreneble, multfadena, sed la surfadena arkitekturo estas malsama ol tiu uzata en brubeck. La fadenoj en brubeck estas la samaj - ĉiu el ili respondecas kaj pri kolekto de informoj kaj kunigo. En bioyino, laboristoj estas dividitaj en du grupojn: tiuj respondecaj pri la reto kaj tiuj respondecaj pri agregado. Ĉi tiu divido permesas vin pli flekse administri la aplikaĵon depende de la tipo de metriko: kie necesas intensa agregado, vi povas aldoni agregantojn, kie estas multe da rettrafiko, vi povas aldoni la nombron da retaj fluoj. Nuntempe, ĉe niaj serviloj ni laboras en 8 reto kaj 4 agregaj fluoj.

La parto de kalkulado (respondeca pri agregado) estas sufiĉe enuiga. Bufroj plenigitaj de retfluoj estas distribuitaj inter nombraj fluoj, kie ili poste estas analizitaj kaj agregitaj. Laŭ peto, metrikoj estas donitaj por sendado al aliaj nodoj. Ĉio ĉi, inkluzive de sendo de datumoj inter nodoj kaj laborado kun Consul, estas farata nesinkrone, funkciante sur la kadro. tokio.

Multe pli da problemoj dum evoluo estis kaŭzitaj de la retoparto respondeca pri ricevado de metrikoj. La ĉefa celo de apartigado de retaj fluoj en apartajn entojn estis la deziro redukti la tempon, kiun fluo pasigas ne por legi datumojn el la ingo. Opcioj uzantaj nesinkronan UDP kaj regulan recvmsg rapide malaperis: la unua konsumas tro multe da uzantspaca CPU por okazaĵa prilaborado, la dua postulas tro multajn kuntekstŝaltilojn. Tial ĝi nun estas uzata recvmmsg kun grandaj bufroj (kaj bufroj, sinjoroj oficiroj, estas nenio por vi!). Subteno por regula UDP estas rezervita por malpezaj kazoj kie recvmmsg ne estas necesa. En plurmesaĝa reĝimo, eblas atingi la ĉefan aferon: la granda plimulto de la tempo, la reto-fadeno rastas la OS-vicon - legas datumojn de la ingo kaj transdonas ĝin al la uzantspaca bufro, nur foje ŝanĝante al doni la plenan bufron al. agregantoj. La vosto en la ingo praktike ne amasiĝas, la nombro da faligitaj pakoj preskaŭ ne kreskas.

Примечание

En la defaŭltaj agordoj, la bufrograndeco estas tre granda. Se vi subite decidas provi la servilon mem, vi eble renkontos la fakton, ke post sendado de malgranda nombro da metrikoj, ili ne alvenos en Grafito, restante en la reto-flua bufro. Por labori kun malgranda nombro da metrikoj, vi devas agordi bufsize kaj task-queue-size al pli malgrandaj valoroj en la agordo.

Finfine, kelkaj furorlisto por furorlistoj.

Statistikoj pri la nombro da envenantaj metrikoj por ĉiu servilo: pli ol 2 milionoj da MPS.

Bioyino - distribuita, skalebla metrika agregatoro

Malebligante unu el la nodoj kaj redistribuante envenantajn metrikojn.

Bioyino - distribuita, skalebla metrika agregatoro

Statistikoj pri eksiĝintaj metrikoj: nur unu nodo ĉiam sendas - la atakestro.

Bioyino - distribuita, skalebla metrika agregatoro

Statistikoj pri la funkciado de ĉiu nodo, konsiderante erarojn en diversaj sistemaj moduloj.

Bioyino - distribuita, skalebla metrika agregatoro

Detaligo de envenantaj metrikoj (metrikaj nomoj estas kaŝitaj).

Bioyino - distribuita, skalebla metrika agregatoro

Kion ni intencas fari kun ĉio ĉi poste? Kompreneble, skribu kodon, diable...! La projekto estis origine planita por esti malfermfonta kaj restos tiel dum sia vivo. Niaj tujaj planoj inkluzivas ŝanĝi al nia propra versio de Raft, ŝanĝi la samrangan protokolon al pli portebla, enkonduki pliajn internajn statistikojn, novajn specojn de metrikoj, korektojn de cimoj kaj aliajn plibonigojn.

Kompreneble, ĉiuj bonvenas helpi en la disvolviĝo de la projekto: krei PR, Temoj, se eble ni respondos, plibonigos, ktp.

Dirite, jen ĉiuj homoj, aĉetu niajn elefantojn!



fonto: www.habr.com

Aldoni komenton