Bioyino - elosztott, méretezhető mérőszám-gyűjtő

Tehát mérőszámokat gyűjt. Ahogy vagyunk. Mutatókat is gyűjtünk. Természetesen az üzlethez szükséges. Ma megfigyelőrendszerünk legelső linkjéről fogunk beszélni - egy statsd-kompatibilis aggregációs szerverről bioyino, miért írtuk és miért hagytuk el a brubecket.

Bioyino - elosztott, méretezhető mérőszám-gyűjtő

Korábbi cikkeinkből (1, 2) megtudhatja, hogy egy ideig a segítségével gyűjtöttük a jeleket Brubeck. C-ben van írva. Kód szempontjából olyan egyszerű, mint egy dugó (ez fontos, ha hozzá szeretne járulni), és ami a legfontosabb, csúcson kezeli a másodpercenkénti 2 millió metrikát (MPS) minden probléma nélkül. A dokumentáció 4 millió MPS támogatását csillaggal jelzi. Ez azt jelenti, hogy a megadott számot kapja, ha megfelelően konfigurálja a hálózatot Linuxon. (Nem tudjuk, hány MPS-t kaphat, ha a hálózatot úgy hagyja, ahogy van). Ezen előnyök ellenére számos komoly panaszunk volt a brubeckkel kapcsolatban.

1. állítás. A Github, a projekt fejlesztője felhagyott a támogatásával: a javítások és javítások közzétételével, a miénk és (nem csak a mi) PR elfogadásával. Az elmúlt hónapokban (valahol 2018. február-márciustól) újraindult a tevékenység, de előtte majdnem 2 év teljes nyugalom volt. Emellett a projekt fejlesztés alatt áll belső Gihub igényekhez, ami komoly akadálya lehet az új funkciók bevezetésének.

2. állítás. A számítások pontossága. Brubeck összesen 65536 értéket gyűjt össze az összesítéshez. Esetünkben egyes mutatók esetében az összesítési periódusban (30 másodperc) sokkal több érték érkezhet (1 527 392 a csúcson). A mintavétel eredményeként a maximális és minimális értékek haszontalannak tűnnek. Például így:

Bioyino - elosztott, méretezhető mérőszám-gyűjtő
Mint volt

Bioyino - elosztott, méretezhető mérőszám-gyűjtő
Milyennek kellett volna lennie

Ugyanezen okból az összegek kiszámítása általában helytelenül történik. Adjunk hozzá egy hibát a 32 bites lebegő túlcsordulással, amely általában segfaultra küldi a szervert, amikor egy látszólag ártatlan mérőszámot kap, és minden nagyszerűvé válik. A hibát egyébként nem javították ki.

És végül, X követelés. A cikk írásakor készek vagyunk bemutatni mind a 14 többé-kevésbé működő statsd implementációnak, amelyet sikerült megtalálnunk. Képzeljük el, hogy néhány infrastruktúra annyira megnőtt, hogy a 4 millió MPS elfogadása már nem elég. Vagy ha még nem is nőtt, de a mutatók már annyira fontosak számodra, hogy már a rövid, 2-3 perces ugrások is kritikussá válhatnak, és leküzdhetetlen depressziós rohamokat okozhatnak a vezetők körében. Mivel a depresszió kezelése hálátlan feladat, technikai megoldásokra van szükség.

Először is a hibatűrés, hogy a szerveren hirtelen fellépő probléma ne okozzon pszichiátriai zombiapokalipszist az irodában. Másodszor, méretezés, hogy képes legyen több mint 4 millió MPS fogadására anélkül, hogy mélyen beleásnánk magunkat a Linux hálózati verembe, és nyugodtan „szélesre” nőne a szükséges méretre.

Mivel volt helyünk a méretezésre, úgy döntöttünk, hogy a hibatűréssel kezdjük. "RÓL RŐL! Hibatűrés! Egyszerű, meg tudjuk csinálni” – gondoltuk, és elindítottunk 2 szervert, mindegyikre felrakva a brubeck másolatát. Ehhez át kellett másolnunk a forgalmat metrikákkal mindkét szerverre, és ehhez még írni is kellett kis közüzemi. Ezzel megoldottuk a hibatűrés problémáját, de... nem túl jól. Eleinte minden nagyszerűnek tűnt: minden brubeck összegyűjti a saját összesítési verzióját, 30 másodpercenként egyszer ír adatokat a Graphite-ba, felülírva a régi intervallumot (ez a grafit oldalon történik). Ha az egyik szerver hirtelen meghibásodik, mindig van egy másik, amelyik saját másolattal rendelkezik az összesített adatokról. De itt van a probléma: ha a szerver meghibásodik, egy „fűrész” jelenik meg a grafikonokon. Ez annak köszönhető, hogy a brubeck 30 másodperces intervallumai nincsenek szinkronban, és az ütközés pillanatában az egyiket nem írja felül. Amikor a második szerver elindul, ugyanez történik. Egészen elviselhető, de jobbat akarok! A méretezhetőség problémája sem szűnt meg. Minden mérőszám továbbra is egyetlen szerverre „repül”, ezért a hálózati szinttől függően ugyanarra a 2-4 millió MPS-re korlátozzuk.

Ha kicsit elgondolkodunk a problémán, és közben havat ásunk egy lapáttal, akkor a következő kézenfekvő ötlet juthat eszünkbe: kell egy statsd, ami elosztott módban is tud működni. Vagyis olyat, amelyik megvalósítja a csomópontok közötti időbeni és mérőszámok közötti szinkronizálást. „Természetesen valószínűleg már létezik ilyen megoldás” – mondtuk, és felkerestük a Google-t…. És nem találtak semmit. Miután átnézte a különböző statsd dokumentációját (https://github.com/etsy/statsd/wiki#server-implementations 11.12.2017. december XNUMX-én) egyáltalán nem találtunk semmit. Úgy látszik, ezeknek a megoldásoknak sem a fejlesztők, sem a felhasználók nem találkoztak még OLYAN sok mérőszámmal, különben biztosan kitalálnának valamit.

És akkor eszünkbe jutott a „játék” statsd - bioyino, amelyet a Just for Fun hackathonon írtak (a projekt nevét a hackathon kezdete előtt a forgatókönyv generálta), és rájöttünk, hogy sürgősen szükségünk van saját statsd-re. Miért?

  • mert túl kevés statsd klón van a világon,
  • mert lehetséges a kívánt vagy ahhoz közeli hibatűrés és skálázhatóság biztosítása (beleértve az összesített mérőszámok szinkronizálását a szerverek között és a küldési konfliktusok megoldását),
  • mert lehetséges a mutatók pontosabb kiszámítása, mint Brubeck,
  • mert te magad is gyűjthetsz részletesebb statisztikákat, amit a brubeck gyakorlatilag nem közölt velünk,
  • mert lehetőségem volt saját hyperperformance distributed scale labor alkalmazásomat programozni, ami nem fogja teljesen megismételni egy másik hasonló hyperfor architektúráját... hát ez van.

Mire kell írni? Természetesen Rustban. Miért?

  • mert már volt prototípus megoldás,
  • mert a cikk írója ekkor már ismerte Rustot, és szívesen írt bele valamit a gyártáshoz azzal a lehetőséggel, hogy nyílt forráskódba helyezze,
  • mert a GC-vel rendelkező nyelvek a fogadott forgalom természetéből adódóan (majdnem valós időben) nem megfelelőek számunkra, és a GC szünetek gyakorlatilag elfogadhatatlanok,
  • mert a C-hez hasonló maximális teljesítményre van szüksége
  • mert a Rust rettenthetetlen egyidejűséget biztosít számunkra, és ha C/C++-ban kezdjük el írni, akkor még több sebezhetőséget, puffertúlcsordulást, versenykörülményeket és egyéb ijesztő szavakat gyűjtöttünk volna be, mint a brubeck.

Volt érv is Rust ellen. A cégnek nem volt tapasztalata projektek létrehozásában Rustban, és most sem tervezzük a fő projektben való felhasználását. Ezért komoly félelmek voltak, hogy semmi sem fog sikerülni, de úgy döntöttünk, hogy megkockáztatjuk és megpróbáltuk.

Eltelt idő...

Végül több sikertelen próbálkozás után elkészült az első működő verzió. Mi történt? Ez történt.

Bioyino - elosztott, méretezhető mérőszám-gyűjtő

Minden csomópont megkapja a saját metrikakészletét, és felhalmozza azokat, és nem összesíti a metrikákat azokhoz a típusokhoz, amelyeknél a teljes készletük szükséges a végső összesítéshez. A csomópontokat valamiféle elosztott zárprotokoll köti össze, amivel kiválasztható közülük az egyetlen (itt sírtunk), amely méltó arra, hogy metrikákat küldjön a Nagynak. Ezt a problémát jelenleg a Konzul, de a jövőben a szerző ambíciói arra is kiterjednek saját végrehajtás Tutaj, ahol a legméltóbb természetesen a konszenzusvezető csomópont lesz. A konszenzus mellett a csomópontok gyakran (alapértelmezés szerint másodpercenként egyszer) elküldik szomszédaiknak az előre összesített metrikák azon részeit, amelyeket abban a másodpercben sikerült összegyűjteniük. Kiderült, hogy a skálázás és a hibatűrés megmarad - minden csomópont még mindig tartalmaz egy teljes mérőszámot, de a mérőszámok már összesítve, TCP-n keresztül kerülnek elküldésre és bináris protokollba kódolva, így a duplikációs költségek jelentősen csökkennek az UDP-hez képest. A meglehetősen nagy számú bejövő mérőszám ellenére a felhalmozás nagyon kevés memóriát és még kevesebb CPU-t igényel. Erősen tömöríthető merticsünk esetében ez csak néhány tíz megabájtnyi adat. További bónuszként nem kapunk szükségtelen adatátírásokat Graphite-ban, mint a burbeck esetében.

A metrikus UDP-csomagok kiegyensúlyozatlanok a hálózati berendezések csomópontjai között egy egyszerű körmérkőzésen keresztül. Természetesen a hálózati hardver nem elemzi a csomagok tartalmát, ezért másodpercenként sokkal több mint 4 millió csomagot tud húzni, nem beszélve azokról a mérőszámokról, amelyekről egyáltalán nem tud. Ha figyelembe vesszük, hogy a mérőszámok nem egyenként jönnek minden csomagban, akkor ezen a helyen nem látunk teljesítménybeli problémákat. Ha egy szerver összeomlik, a hálózati eszköz gyorsan (1-2 másodpercen belül) észleli ezt a tényt, és eltávolítja az összeomlott szervert a forgásból. Ennek eredményeként a passzív (azaz nem vezető) csomópontok gyakorlatilag anélkül kapcsolhatók be és ki, hogy a diagramokon csökkenést észlelnének. A maximum, amit veszítünk, az az utolsó másodpercben bejött mutatók része. Egy vezető hirtelen elvesztése/leállása/váltása továbbra is kisebb anomáliát okoz (a 30 másodperces intervallum még mindig nincs szinkronban), de ha van kommunikáció a csomópontok között, ezek a problémák minimalizálhatók, például szinkronizálási csomagok kiküldésével. .

Egy kicsit a belső szerkezetről. Az alkalmazás természetesen többszálas, de a szálfűzési architektúra eltér a brubeckben használttól. A brubeck szálai ugyanazok – mindegyik felelős az információgyűjtésért és az összesítésért. A bioyinóban a dolgozókat két csoportra osztják: a hálózatért és az aggregációért felelősekre. Ez a felosztás lehetővé teszi az alkalmazás rugalmasabb kezelését a mérőszámok típusától függően: ahol intenzív aggregációra van szükség, ott aggregátorokat adhatunk hozzá, ahol nagy a hálózati forgalom, ott a hálózati áramlások számát. Szervereinken jelenleg 8 hálózati és 4 aggregációs folyamatban dolgozunk.

A számlálás (az összesítésért felelős) rész elég unalmas. A hálózati áramlásokkal feltöltött pufferek elosztásra kerülnek a számláló folyamok között, ahol ezt követően elemzik és összesítik. Kérésre metrikákat adunk a többi csomópontnak való elküldéshez. Mindez, beleértve a csomópontok közötti adatküldést és a Consul-lal való együttműködést, aszinkron módon, a keretrendszeren fut. Tokió.

A fejlesztés során sokkal több problémát okozott a mérőszámok fogadásáért felelős hálózati rész. A hálózati áramlások külön entitásokra való szétválasztásának fő célja az volt, hogy csökkentsék az áramlás által eltöltött időt nincs adatokat olvasni az aljzatból. Az aszinkron UDP-t és a normál recvmsg-t használó lehetőségek gyorsan eltűntek: az első túl sok felhasználói helyet foglal el az eseményfeldolgozáshoz, a második túl sok kontextuskapcsolót igényel. Ezért most használják recvmmsg nagy ütközőkkel (és az ütközők, tiszt uraim, önöknek semmiség!). A normál UDP támogatása olyan könnyű esetekre van fenntartva, amikor nincs szükség recvmmsg-re. Multimessage módban a lényeget el lehet érni: az esetek túlnyomó részében a hálózati szál gereblyézi az OS-sort - kiolvassa az adatokat a socketből és továbbítja a felhasználói terület pufferébe, csak alkalmanként vált át a feltöltött puffer átadására. aggregátorok. A foglalatban lévő sor gyakorlatilag nem halmozódik fel, az elejtett csomagok száma gyakorlatilag nem nő.

Megjegyzés

Az alapértelmezett beállításokban a puffer mérete meglehetősen nagyra van állítva. Ha hirtelen úgy döntesz, hogy magad is kipróbálod a szervert, akkor szembesülhetsz azzal, hogy kisszámú metrika elküldése után nem érkeznek meg a Graphite-ba, a hálózati stream pufferben maradnak. Ha kis számú metrikával szeretne dolgozni, a konfigurációban a bufsize és a task-queue-size értékeket kisebb értékekre kell állítania.

Végül néhány grafikon a chartok szerelmeseinek.

Statisztikák az egyes szerverekhez bejövő metrikák számáról: több mint 2 millió MPS.

Bioyino - elosztott, méretezhető mérőszám-gyűjtő

Az egyik csomópont letiltása és a bejövő metrikák újraelosztása.

Bioyino - elosztott, méretezhető mérőszám-gyűjtő

Statisztikák a kimenő mérőszámokról: mindig csak egy csomópont küld - a raid boss.

Bioyino - elosztott, méretezhető mérőszám-gyűjtő

Az egyes csomópontok működésének statisztikája, figyelembe véve a különböző rendszermodulok hibáit.

Bioyino - elosztott, méretezhető mérőszám-gyűjtő

A bejövő mutatók részletezése (a mérőszámok nevei el vannak rejtve).

Bioyino - elosztott, méretezhető mérőszám-gyűjtő

Mit tervezünk ezután mindezzel? Persze, írj kódot, a fenébe...! A projektet eredetileg nyílt forráskódúnak tervezték, és az egész élettartama alatt az is marad. Közvetlen terveink között szerepel a Raft saját verziójára való váltás, a peer protokoll cseréje egy hordozhatóbbra, további belső statisztikák bevezetése, új típusú mérőszámok, hibajavítások és egyéb fejlesztések.

Természetesen mindenkit szeretettel várunk, hogy segítsen a projekt kidolgozásában: PR, Issues készítés, lehetőség szerint reagálunk, javítunk stb.

Ezzel együtt ennyi, emberek, vegyétek meg az elefántjainkat!



Forrás: will.com

Hozzászólás