Així que recopileu mètriques. Com som nosaltres. També recollim mètriques. Per descomptat, necessari per als negocis. Avui parlarem del primer enllaç del nostre sistema de monitorització: un servidor d'agregació compatible amb statsd
Dels nostres articles anteriors (
Reclamació 1. Github, el desenvolupador del projecte, va deixar de donar-li suport: publicant pedaços i correccions, acceptant el nostre i (no només el nostre) PR. En els darrers mesos (entre febrer-març del 2018), l'activitat s'ha reprès, però abans hi havia gairebé 2 anys de calma total. A més, s'està desenvolupant el projecte
Reclamació 2. Exactitud dels càlculs. Brubeck recull un total de 65536 valors per a l'agregació. En el nostre cas, per a algunes mètriques, durant el període d'agregació (30 segons), poden arribar molts més valors (1 al pic). Com a resultat d'aquest mostreig, els valors màxim i mínim semblen inútils. Per exemple, així:
Tal com va ser
Com hauria d'haver estat
Per la mateixa raó, les quantitats generalment es calculen incorrectament. Afegiu aquí un error amb un desbordament flotant de 32 bits, que generalment envia el servidor a un error de seg quan rep una mètrica aparentment innocent, i tot es farà genial. L'error, per cert, no s'ha corregit.
I, finalment, Reclamació X. En el moment d'escriure aquest article, estem preparats per presentar-lo a les 14 implementacions d'estadístiques més o menys funcionals que hem pogut trobar. Imaginem que una sola infraestructura ha crescut tant que acceptar 4 milions de MPS ja no n'hi ha prou. O fins i tot si encara no ha crescut, però les mètriques ja són tan importants per a tu que fins i tot caigudes curtes de 2-3 minuts als gràfics ja poden arribar a ser crítiques i provocar atacs de depressió insuperable entre els directius. Com que tractar la depressió és una tasca ingrata, calen solucions tècniques.
En primer lloc, la tolerància a errors, perquè un problema sobtat al servidor no provoqui un apocalipsi psiquiàtric zombi a l'oficina. En segon lloc, escalar per poder acceptar més de 4 milions de MPS, sense aprofundir en la pila de xarxa de Linux i créixer amb calma "en amplitud" fins a la mida requerida.
Com que teníem espai per escalar, vam decidir començar amb la tolerància a fallades. "SOBRE! Falta de tolerància! És senzill, ho podem fer”, vam pensar i vam llançar 2 servidors, aixecant una còpia de brubeck a cadascun. Per fer-ho, vam haver de copiar el trànsit amb mètriques als dos servidors i fins i tot escriure per a això
Si penseu una mica en el problema i al mateix temps desenterrau neu amb una pala, us pot venir al cap la següent idea òbvia: necessiteu una estadística que pugui funcionar en mode distribuït. És a dir, un que implementa la sincronització entre nodes en temps i mètriques. "Per descomptat, aquesta solució probablement ja existeix", vam dir i vam anar a Google... I no van trobar res. Després de revisar la documentació de diferents estadístiques (
I aleshores vam recordar les estadístiques de "joguina" - bioyino, que es van escriure al hackathon Just for Fun (el nom del projecte va ser generat pel guió abans de l'inici del hackathon) i ens vam adonar que necessitàvem urgentment les nostres pròpies estadístiques. Per a què?
- perquè hi ha massa pocs clons d'estadístiques al món,
- perquè és possible proporcionar la tolerància a errors i escalabilitat desitjades o properes a les desitjades (inclosa la sincronització de mètriques agregades entre servidors i la resolució del problema de l'enviament de conflictes),
- perquè és possible calcular mètriques amb més precisió que Brubeck,
- perquè podeu recopilar estadístiques més detallades, que Brubeck pràcticament no ens va proporcionar,
- perquè vaig tenir l'oportunitat de programar la meva pròpia aplicació de laboratori d'escala distribuïda d'hiperrendiment, que no repetirà completament l'arquitectura d'un altre hiperperformance semblant... bé, això és tot.
En què escriure? Això sí, a Rust. Per què?
- perquè ja hi havia una solució prototip,
- perquè l'autor de l'article ja coneixia Rust en aquell moment i tenia ganes d'escriure alguna cosa per a la producció amb l'oportunitat de posar-lo en codi obert,
- perquè els idiomes amb GC no ens són adequats a causa de la naturalesa del trànsit rebut (gairebé en temps real) i les pauses de GC són pràcticament inacceptables,
- perquè necessiteu un rendiment màxim comparable al C
- perquè Rust ens proporciona una concurrència sense por, i si haguéssim començat a escriure-ho en C/C++, hauríem acumulat encara més vulnerabilitats, desbordaments de memòria intermèdia, condicions de carrera i altres paraules espantoses que brubeck.
També hi va haver un argument contra Rust. L'empresa no tenia experiència creant projectes a Rust, i ara tampoc tenim previst utilitzar-lo en el projecte principal. Per tant, hi havia greus temors que res no funcionés, però vam decidir arriscar i ho vam intentar.
El temps va passar...
Finalment, després de diversos intents fallits, la primera versió de treball estava a punt. Què va passar? Això és el que va passar.
Cada node rep el seu propi conjunt de mètriques i les acumula, i no agrega mètriques per a aquells tipus on es requereix el seu conjunt complet per a l'agregació final. Els nodes estan connectats entre si mitjançant algun tipus de protocol de bloqueig distribuït, que permet seleccionar entre ells l'únic (aquí vam plorar) que mereix enviar mètriques al Gran. Aquest problema està sent resolt actualment per
Els paquets UDP amb mètriques es desequilibren entre els nodes dels equips de xarxa mitjançant un simple Round Robin. Per descomptat, el maquinari de xarxa no analitza el contingut dels paquets i, per tant, pot extreure molt més de 4 milions de paquets per segon, per no parlar de mètriques de les quals no sap res. Si tenim en compte que les mètriques no surten d'una en una a cada paquet, no preveiem cap problema de rendiment en aquest lloc. Si un servidor falla, el dispositiu de xarxa ràpidament (en 1-2 segons) detecta aquest fet i elimina el servidor bloquejat de la rotació. Com a resultat d'això, els nodes passius (és a dir, no líders) es poden activar i desactivar pràcticament sense notar inconvenients als gràfics. El màxim que perdem és part de les mètriques que han arribat a l'últim segon. Una pèrdua/apagada/canvi sobtada d'un líder encara crearà una petita anomalia (l'interval de 30 segons encara no està sincronitzat), però si hi ha comunicació entre nodes, aquests problemes es poden minimitzar, per exemple, enviant paquets de sincronització. .
Una mica sobre l'estructura interna. L'aplicació és, per descomptat, multiprocés, però l'arquitectura de fils és diferent de la que s'utilitza a Brubeck. Els fils de brubeck són els mateixos: cadascun d'ells és responsable tant de la recollida d'informació com de l'agregació. A bioyino, els treballadors es divideixen en dos grups: els responsables de la xarxa i els responsables de l'agregació. Aquesta divisió permet gestionar l'aplicació de manera més flexible en funció del tipus de mètriques: on es requereix una agregació intensiva, es poden afegir agregadors, on hi ha molt trànsit de xarxa, es pot afegir el nombre de fluxos de xarxa. Actualment, als nostres servidors treballem en 8 fluxos de xarxa i 4 d'agregació.
La part del recompte (responsable de l'agregació) és força avorrida. Els buffers omplerts pels fluxos de xarxa es distribueixen entre els fluxos de recompte, on posteriorment s'analitzen i s'agreguen. A petició, es donen mètriques per enviar-les a altres nodes. Tot això, inclòs l'enviament de dades entre nodes i el treball amb Consul, es realitza de manera asíncrona, s'executa al framework
Molts més problemes durant el desenvolupament van ser causats per la part de xarxa responsable de rebre mètriques. L'objectiu principal de separar els fluxos de xarxa en entitats separades era el desig de reduir el temps que passa un flux no per llegir dades del sòcol. Les opcions que utilitzaven UDP asíncron i recvmsg regular van desaparèixer ràpidament: el primer consumeix massa CPU d'espai d'usuari per al processament d'esdeveniments, el segon requereix massa canvis de context. Per tant, ara s'utilitza
Nota
A la configuració predeterminada, la mida de la memòria intermèdia està configurada per ser bastant gran. Si de sobte decideixes provar el servidor tu mateix, és possible que et trobis amb el fet que després d'enviar un nombre reduït de mètriques, no arribaran a Graphite, romanent a la memòria intermèdia de la xarxa. Per treballar amb un nombre reduït de mètriques, heu d'establir la mida de bus i la mida de la cua de tasques en valors més petits a la configuració.
Finalment, algunes cartes per als amants de les cartes.
Estadístiques sobre el nombre de mètriques entrants per a cada servidor: més de 2 milions de MPS.
Desactivar un dels nodes i redistribuir les mètriques entrants.
Estadístiques sobre mètriques de sortida: només envia un node: el cap de la incursió.
Estadístiques del funcionament de cada node, tenint en compte els errors en diversos mòduls del sistema.
Detall de les mètriques entrants (els noms de les mètriques estan ocults).
Què tenim previst fer amb tot això a continuació? Això sí, escriu codi, carai...! El projecte es va plantejar inicialment per ser de codi obert i ho mantindrà durant tota la seva vida. Els nostres plans immediats inclouen canviar a la nostra pròpia versió de Raft, canviar el protocol d'iguals a un de més portàtil, introduir estadístiques internes addicionals, nous tipus de mètriques, correccions d'errors i altres millores.
Per descomptat, tothom és benvingut a ajudar en el desenvolupament del projecte: crear PR, Issues, si és possible respondrem, millorarem, etc.
Dit això, això és tot gent, compra els nostres elefants!
Font: www.habr.com