Sie sammeln also Kennzahlen. Wie wir sind. Wir erfassen auch Kennzahlen. Natürlich geschäftsnotwendig. Heute werden wir über den allerersten Link unseres Überwachungssystems sprechen – einen Statsd-kompatiblen Aggregationsserver
Aus unseren vorherigen Artikeln (
Anspruch 1. Github, der Entwickler des Projekts, hat aufgehört, es zu unterstützen: Patches und Fixes zu veröffentlichen, unsere und (nicht nur unsere) PR zu akzeptieren. In den letzten Monaten (irgendwann von Februar bis März 2018) hat die Aktivität wieder zugenommen, davor herrschte jedoch fast zwei Jahre völlige Ruhe. Darüber hinaus befindet sich das Projekt in der Entwicklung
Anspruch 2. Genauigkeit der Berechnungen. Insgesamt sammelt Brubeck 65536 Werte zur Aggregation. In unserem Fall können für einige Metriken während des Aggregationszeitraums (30 Sekunden) viel mehr Werte eintreffen (1 in der Spitze). Als Ergebnis dieser Stichprobe erscheinen die Maximal- und Minimalwerte unbrauchbar. Zum Beispiel so:
Wie war
Wie es hätte sein sollen
Aus dem gleichen Grund werden Beträge in der Regel falsch berechnet. Fügen Sie hier einen Fehler mit einem 32-Bit-Float-Überlauf hinzu, der den Server im Allgemeinen in einen Segfault schickt, wenn er eine scheinbar harmlose Metrik empfängt, und alles wird großartig. Der Fehler wurde übrigens nicht behoben.
Und endlich, Anspruch X. Zum Zeitpunkt des Schreibens sind wir bereit, es allen 14 mehr oder weniger funktionierenden Statsd-Implementierungen vorzustellen, die wir finden konnten. Stellen wir uns vor, dass eine einzelne Infrastruktur so stark gewachsen ist, dass die Annahme von 4 Millionen MPS nicht mehr ausreicht. Oder auch wenn es noch nicht gewachsen ist, aber die Kennzahlen für Sie bereits so wichtig sind, dass selbst kurze Einbrüche in den Diagrammen von 2 bis 3 Minuten bereits kritisch werden und bei Managern unüberwindbare Depressionen auslösen können. Da die Behandlung von Depressionen eine undankbare Aufgabe ist, sind technische Lösungen erforderlich.
Erstens Fehlertoleranz, damit ein plötzliches Problem auf dem Server nicht zu einer psychiatrischen Zombie-Apokalypse im Büro führt. Zweitens die Skalierung, um mehr als 4 Millionen MPS akzeptieren zu können, ohne tief in den Linux-Netzwerkstapel einzudringen und ruhig „in der Breite“ auf die erforderliche Größe zu wachsen.
Da wir Spielraum für Skalierung hatten, entschieden wir uns, mit der Fehlertoleranz zu beginnen. "UM! Fehlertoleranz! Es ist ganz einfach, wir schaffen das“, dachten wir und starteten zwei Server, auf denen wir jeweils eine Kopie von Brubeck erstellten. Dazu mussten wir den Traffic mit Metriken auf beide Server kopieren und dafür sogar schreiben
Wenn man ein wenig über das Problem nachdenkt und gleichzeitig mit einer Schaufel Schnee ausgräbt, dann kommt einem vielleicht folgende offensichtliche Idee in den Sinn: Man braucht einen Statsd, der im verteilten Modus arbeiten kann. Das heißt, eines, das die zeitliche und metrische Synchronisierung zwischen Knoten implementiert. „Natürlich gibt es eine solche Lösung wahrscheinlich schon“, sagten wir und gingen zu Google…. Und sie fanden nichts. Nachdem Sie die Dokumentation für verschiedene Statistiken durchgesehen haben (
Und dann erinnerten wir uns an den „Spielzeug“-Statsd – bioyino, der beim Just for Fun-Hackathon geschrieben wurde (der Name des Projekts wurde vom Skript vor Beginn des Hackathons generiert) und erkannten, dass wir dringend einen eigenen Statsd brauchten. Wofür?
- weil es zu wenige Statsd-Klone auf der Welt gibt,
- weil es möglich ist, die gewünschte oder nahezu gewünschte Fehlertoleranz und Skalierbarkeit bereitzustellen (einschließlich der Synchronisierung aggregierter Metriken zwischen Servern und der Lösung des Problems von Sendekonflikten),
- weil es möglich ist, Kennzahlen genauer zu berechnen als Brubeck,
- weil Sie selbst detailliertere Statistiken sammeln können, die Brubeck uns praktisch nicht zur Verfügung gestellt hat,
- weil ich die Chance hatte, meine eigene Hyperperformance-Laboranwendung mit verteiltem Maßstab zu programmieren, die die Architektur eines anderen ähnlichen Hyperfor nicht vollständig wiederholen wird ... nun, das war's.
Worüber soll ich schreiben? Natürlich in Rust. Warum?
- weil es bereits eine prototypische Lösung gab,
- weil der Autor des Artikels Rust zu diesem Zeitpunkt bereits kannte und unbedingt etwas für die Produktion darin schreiben wollte, mit der Möglichkeit, es in Open Source zu veröffentlichen,
- weil Sprachen mit GC aufgrund der Art des empfangenen Datenverkehrs (fast in Echtzeit) für uns nicht geeignet sind und GC-Pausen praktisch inakzeptabel sind,
- weil Sie eine maximale Leistung benötigen, die mit C vergleichbar ist
- weil Rust uns eine furchtlose Parallelität bietet, und wenn wir angefangen hätten, es in C/C++ zu schreiben, hätten wir noch mehr Schwachstellen, Pufferüberläufe, Rennbedingungen und andere beängstigende Wörter als Brubeck eingebracht.
Es gab auch ein Argument gegen Rust. Das Unternehmen hatte keine Erfahrung mit der Erstellung von Projekten in Rust und jetzt planen wir auch nicht, es im Hauptprojekt zu verwenden. Daher gab es ernsthafte Befürchtungen, dass nichts klappen würde, aber wir beschlossen, ein Risiko einzugehen und versuchten es.
Zeit verging...
Nach mehreren gescheiterten Versuchen war endlich die erste funktionsfähige Version fertig. Was ist passiert? Das ist, was passiert ist.
Jeder Knoten empfängt seinen eigenen Satz von Metriken und akkumuliert diese. Er aggregiert keine Metriken für die Typen, bei denen der vollständige Satz für die endgültige Aggregation erforderlich ist. Die Knoten sind durch eine Art verteiltes Sperrprotokoll miteinander verbunden, das es Ihnen ermöglicht, unter ihnen den einzigen auszuwählen (hier haben wir geweint), der es wert ist, Metriken an den Großen zu senden. Dieses Problem wird derzeit von gelöst
UDP-Pakete mit Metriken werden durch ein einfaches Round Robin zwischen Knoten auf Netzwerkgeräten unausgeglichen. Natürlich analysiert die Netzwerkhardware den Inhalt von Paketen nicht und kann daher weit mehr als 4 Millionen Pakete pro Sekunde abrufen, ganz zu schweigen von Metriken, über die sie überhaupt nichts weiß. Wenn wir berücksichtigen, dass die Metriken nicht einzeln in jedem Paket enthalten sind, können wir an dieser Stelle keine Leistungsprobleme erwarten. Wenn ein Server abstürzt, erkennt das Netzwerkgerät dies schnell (innerhalb von 1–2 Sekunden) und entfernt den abgestürzten Server aus der Rotation. Dadurch können passive (d. h. nicht führende) Knoten ein- und ausgeschaltet werden, praktisch ohne dass Drawdowns auf den Diagrammen zu bemerken sind. Das Maximum, das wir verlieren, ist Teil der Messwerte, die in letzter Sekunde eingegangen sind. Ein plötzlicher Verlust/Abschaltung/Wechsel eines Leiters führt immer noch zu einer geringfügigen Anomalie (das 30-Sekunden-Intervall ist immer noch nicht synchron), wenn jedoch Kommunikation zwischen Knoten besteht, können diese Probleme minimiert werden, indem beispielsweise Synchronisierungspakete gesendet werden .
Ein wenig über die interne Struktur. Die Anwendung ist natürlich multithreaded, aber die Threading-Architektur unterscheidet sich von der in Brubeck verwendeten. Die Threads in Brubeck sind die gleichen – jeder von ihnen ist sowohl für die Informationssammlung als auch für die Aggregation verantwortlich. Im Bioyino werden die Arbeiter in zwei Gruppen eingeteilt: diejenigen, die für das Netzwerk verantwortlich sind, und diejenigen, die für die Aggregation verantwortlich sind. Diese Unterteilung ermöglicht Ihnen eine flexiblere Verwaltung der Anwendung je nach Art der Metriken: Wo eine intensive Aggregation erforderlich ist, können Sie Aggregatoren hinzufügen, wo viel Netzwerkverkehr herrscht, können Sie die Anzahl der Netzwerkflüsse hinzufügen. Derzeit arbeiten wir auf unseren Servern in 8 Netzwerk- und 4 Aggregationsflüssen.
Der Zählteil (der für die Aggregation verantwortlich ist) ist ziemlich langweilig. Durch Netzwerkflüsse gefüllte Puffer werden auf die Zählflüsse verteilt, wo sie anschließend analysiert und aggregiert werden. Auf Anfrage werden Metriken zum Senden an andere Knoten bereitgestellt. All dies, einschließlich des Sendens von Daten zwischen Knoten und der Arbeit mit Consul, wird asynchron ausgeführt und auf dem Framework ausgeführt
Viel mehr Probleme während der Entwicklung verursachte der Netzwerkteil, der für den Empfang von Metriken verantwortlich ist. Das Hauptziel der Aufteilung von Netzwerkflüssen in separate Einheiten war der Wunsch, die Zeit zu reduzieren, die ein Fluss verbringt nicht um Daten aus dem Socket zu lesen. Optionen, die asynchrones UDP und reguläres recvmsg verwenden, verschwanden schnell: Ersteres verbraucht zu viel Benutzerraum-CPU für die Ereignisverarbeitung, zweites erfordert zu viele Kontextwechsel. Deshalb wird es jetzt verwendet
Beachten
In den Standardeinstellungen ist die Puffergröße recht groß eingestellt. Wenn Sie sich plötzlich dazu entschließen, den Server selbst auszuprobieren, kann es sein, dass nach dem Senden einer kleinen Anzahl von Metriken diese nicht in Graphite ankommen und im Netzwerk-Stream-Puffer verbleiben. Um mit einer kleinen Anzahl von Metriken zu arbeiten, müssen Sie bufsize und task-queue-size in der Konfiguration auf kleinere Werte setzen.
Zum Schluss noch ein paar Charts für Chartliebhaber.
Statistiken zur Anzahl eingehender Metriken für jeden Server: mehr als 2 Millionen MPS.
Einen der Knoten deaktivieren und eingehende Metriken neu verteilen.
Statistiken zu ausgehenden Metriken: Es sendet immer nur ein Knoten – der Raid-Boss.
Statistiken über den Betrieb jedes Knotens unter Berücksichtigung von Fehlern in verschiedenen Systemmodulen.
Detaillierung der eingehenden Metriken (Metriknamen werden ausgeblendet).
Was haben wir als nächstes mit all dem vor? Natürlich Code schreiben, verdammt...! Das Projekt war ursprünglich als Open-Source-Projekt geplant und wird dies auch während seiner gesamten Laufzeit bleiben. Zu unseren unmittelbaren Plänen gehören die Umstellung auf unsere eigene Version von Raft, die Änderung des Peer-Protokolls auf ein tragbareres Protokoll, die Einführung zusätzlicher interner Statistiken, neuer Arten von Metriken, Fehlerbehebungen und anderer Verbesserungen.
Natürlich ist jeder willkommen, bei der Entwicklung des Projekts mitzuhelfen: PR erstellen, Issues erstellen, wenn möglich reagieren wir, verbessern usw.
Nachdem dies gesagt ist, das ist alles, Leute, kauft unsere Elefanten!
Source: habr.com