Wednesday 8 November 2017

Rd Gleitender Durchschnitt


Graphit 1 führt zwei ziemlich einfache Aufgaben: das Speichern von Zahlen, die im Laufe der Zeit ändern und grafisch darzustellen. Im Laufe der Jahre wurde viel Software geschrieben, um diese Aufgaben zu lösen. Was Graphite einzigartig macht, ist, dass es diese Funktionalität als Netzwerkdienst bietet, der sowohl einfach zu bedienen als auch hoch skalierbar ist. Das Protokoll für die Einspeisung von Daten in Graphite ist einfach genug, dass Sie lernen, es von Hand zu tun in ein paar Minuten (nicht, dass Sie tatsächlich wollen, aber seine eine anständige Lackmus-Test für Einfachheit). Rendering Graphen und Abrufen von Datenpunkten sind so einfach wie das Abrufen einer URL. Dies macht es sehr natürlich, Graphite mit anderer Software zu integrieren und ermöglicht es Benutzern, leistungsstarke Anwendungen auf Graphite zu bauen. Eine der häufigsten Anwendungen von Graphite ist der Aufbau von Web-basierten Dashboards für die Überwachung und Analyse. Graphite wurde in einem hochvolumigen E-Commerce-Umfeld geboren und sein Design spiegelt dies wider. Skalierbarkeit und Echtzeit-Zugriff auf Daten sind wichtige Ziele. Die Komponenten, die Graphite diese Ziele erreichen können, umfassen eine spezielle Datenbankbibliothek und ihr Speicherformat, einen Caching-Mechanismus zur Optimierung von IO-Operationen und eine einfache, aber effektive Methode zum Clustering von Graphite-Servern. Anstatt einfach nur zu beschreiben, wie Graphite heute funktioniert, werde ich erklären, wie Graphite ursprünglich implementiert wurde (ganz naiv), welche Probleme ich lief und wie ich Lösungen für sie entwickelte. 7.1. Die Datenbankbibliothek: Speichern von Zeitreihen-Daten Graphit wird vollständig in Python geschrieben und besteht aus drei Hauptkomponenten: einer Datenbankbibliothek mit dem Namen whisper. Ein Back-End-Daemon mit dem Namen carbon. Und ein Front-End-Webapp, das Graphen gerendert und eine grundlegende Benutzeroberfläche bereitstellt. Während Whisper speziell für Graphite geschrieben wurde, kann es auch unabhängig verwendet werden. Es ist sehr ähnlich in der Gestaltung der Round-Robin-Datenbank von RRDtool verwendet, und speichert nur Zeitreihen numerische Daten. In der Regel denken wir an Datenbanken als Server-Prozesse, die Client-Anwendungen sprechen über Sockets. Allerdings, flüstern. Ähnlich wie RRDtool, ist eine Datenbankbibliothek, die von Anwendungen verwendet wird, um Daten, die in speziell formatierten Dateien gespeichert sind, zu manipulieren und abzurufen. Die einfachsten Flüsteroperationen sind das Erstellen einer neuen Flüsterdatei, das Aktualisieren, um neue Datenpunkte in eine Datei zu schreiben und um Datenpunkte abzurufen. Abbildung 7.1: Grundlegende Anatomie einer Flüsterdatei Abbildung 7.1. Whisper-Dateien bestehen aus einem Header-Bereich mit verschiedenen Metadaten, gefolgt von einem oder mehreren Archivbereichen. Jedes Archiv ist eine Folge von aufeinanderfolgenden Datenpunkten, die Paare (Zeitstempel, Wert) sind. Wenn eine Aktualisierungs - oder Abrufoperation ausgeführt wird, bestimmt whisper den Offset in der Datei, auf die Daten geschrieben oder gelesen werden sollen, basierend auf dem Zeitstempel und der Archivkonfiguration. 7.2. Das Backend: Ein einfaches Storage Service Graphites Backend ist ein Daemon-Prozess namens Carbon-Cache. Üblicherweise einfach als Kohlenstoff bezeichnet. Es basiert auf Twisted, einem hoch skalierbaren, ereignisgesteuerten IO-Framework für Python. Twisted ermöglicht es Carbon effizient mit einer großen Anzahl von Clients zu kommunizieren und eine große Menge an Traffic mit geringem Overhead zu behandeln. Abbildung 7.2 zeigt den Datenfluss von Kohlenstoff. Whisper und die Webapp: Client-Anwendungen sammeln Daten und senden sie an die Graphite-Back-End, Kohlenstoff. Die die Daten mittels Flüstern speichert. Diese Daten können dann vom Graphite webapp verwendet werden, um Graphen zu erzeugen. Abbildung 7.2: Datenfluss Die primäre Funktion von Carbon ist die Speicherung von Datenpunkten für Metriken, die von Clients bereitgestellt werden. In der Graphite-Terminologie ist eine Metrik eine beliebige messbare Größe, die über die Zeit variieren kann (wie die CPU-Auslastung eines Servers oder die Anzahl der Verkäufe eines Produkts). Ein Datenpunkt ist einfach ein (Zeitstempel-, Wert-) Paar, das dem gemessenen Wert einer bestimmten Metrik zu einem Zeitpunkt entspricht. Metriken werden durch ihren Namen eindeutig identifiziert, und der Name jeder Metrik sowie ihre Datenpunkte werden durch Client-Anwendungen bereitgestellt. Eine gängige Clientanwendung ist ein Überwachungsagent, der System - oder Anwendungsmetriken sammelt und die gesammelten Werte an Carbon zur einfachen Speicherung und Visualisierung sendet. Metriken in Graphite haben einfache hierarchische Namen, ähnlich wie Dateisystempfade, außer dass ein Punkt verwendet wird, um die Hierarchie zu begrenzen, anstatt einen Schrägstrich oder Backslash. Kohlenstoff wird jeden gesetzlichen Namen respektieren und eine Flüsterdatei für jede Metrik erstellen, um ihre Datenpunkte zu speichern. Die Whisper-Dateien werden im Carbon-Data-Verzeichnis in einer Dateisystemhierarchie gespeichert, die die dotbegrenzte Hierarchie in jedem Metrics-Namen widerspiegelt, sodass (zB) servers. www01.cpuUsage Karten zu hellipserverswww01cpuUsage. wsp abbildet. Wenn eine Client-Anwendung Datenpunkte an Graphite senden möchte, muss sie eine TCP-Verbindung zu Carbon herstellen. Normalerweise auf Hafen 2003 2. Der Klient tut alle sprechenden Kohlenstoff sendet nichts über der Verbindung. Der Client sendet Datenpunkte in einem einfachen Klartextformat, während die Verbindung offen gelassen und bei Bedarf wieder verwendet werden kann. Das Format ist eine Textzeile pro Datenpunkt, wobei jede Zeile den punktierten Metriknamen, den Wert und einen Unix-Zeitstempel enthält, der durch Leerzeichen getrennt ist. Zum Beispiel kann ein Client senden: Auf einer hohen Ebene, alle Kohlenstoff tut ist für Daten in diesem Format zu hören und versuchen, es auf der Festplatte so schnell wie möglich mit Flüstern speichern. Später werden wir die Details einiger Tricks besprechen, die verwendet werden, um Skalierbarkeit sicherzustellen und die beste Leistung zu erhalten, die wir aus einer typischen Festplatte heraus erhalten können. 7.3. Das Front-End: Graphs On-Demand Das Graphite Webapp ermöglicht es Benutzern, benutzerdefinierte Graphen mit einer einfachen URL-basierten API anzufordern. Grafikparameter werden in der Abfragezeichenfolge einer HTTP-GET-Anforderung angegeben und ein PNG-Bild wird als Antwort zurückgegeben. Beispielsweise fordert die URL: einen 500-mal300-Graphen für die Metrik servers. www01.cpuUsage und die letzten 24 Stunden von Daten an. Tatsächlich ist nur der Zielparameter erforderlich, alle anderen sind optional und verwenden Ihre Standardwerte, wenn nicht angegeben. Graphite unterstützt eine Vielzahl von Anzeigeoptionen sowie Datenmanipulationsfunktionen, die einer einfachen funktionalen Syntax folgen. Zum Beispiel könnten wir einen gleitenden 10-Punkte-Durchschnitt der Metrik in unserem vorherigen Beispiel wie folgt graphisch darstellen: Funktionen können verschachtelt werden, was komplexe Ausdrücke und Berechnungen ermöglicht. Hier ist ein weiteres Beispiel, dass die laufende Summe der Verkäufe für den Tag mit Pro-Produkt-Metriken von Umsatz-pro-Minute: Die sumSeries-Funktion berechnet eine Zeitreihe, die die Summe der einzelnen Metrik entspricht dem Muster products..salesPerMinute ist. Dann berechnet das Integral eine laufende Summe und nicht eine Anzahl pro Minute. Von hier aus ist es nicht zu schwer, sich vorzustellen, wie man eine Web-Benutzeroberfläche zum Anzeigen und Manipulieren von Graphen erstellen könnte. Graphit verfügt über eine eigene Composer-Benutzeroberfläche (siehe Abbildung 7.3). Dass dies mit Javascript, um die Grafik-URL-Parameter zu ändern, wie der Benutzer klickt durch die Menüs der verfügbaren Features. Abbildung 7.3: Graphits Composer Interface 7.4. Dashboards Seit seiner Gründung wurde Graphit als Werkzeug für die Erstellung von webbasierten Dashboards verwendet. Die URL-API macht dies zu einem natürlichen Anwendungsfall. Das Erstellen eines Dashboards ist so einfach wie das Erstellen einer HTML-Seite mit Tags wie diesem: Jedoch liebt nicht jeder Handwerk URLs von Hand, so Graphites Composer UI bietet eine Point-and-Click-Methode, um ein Diagramm, aus dem Sie einfach kopieren und erstellen können Fügen Sie die URL ein. Wenn mit einem anderen Tool, das schnelle Erstellung von Webseiten (wie ein Wiki) ermöglicht wird, wird dies einfach genug, dass nicht-technische Benutzer können ihre eigenen Dashboards ziemlich leicht zu bauen. 7,5. Ein offensichtlicher Bottleneck Sobald meine Benutzer mit dem Erstellen von Dashboards begannen, begann Graphite schnell Leistungsprobleme zu haben. Ich untersuchte die Web-Server-Protokolle, um zu sehen, was Anfragen waren bogging es nach unten. Es war ziemlich offensichtlich, dass das Problem die schiere Anzahl der graphischen Anforderungen war. Der webapp war CPU-gebunden und grafisch grafisch darzustellen. Ich bemerkte, dass es viele identische Anfragen gab und die Dashboards waren schuld. Stellen Sie sich vor, Sie haben ein Armaturenbrett mit 10 Grafiken in ihm und die Seite aktualisiert einmal pro Minute. Jedes Mal, wenn ein Benutzer das Dashboard in seinem Browser öffnet, muss Graphite 10 weitere Anfragen pro Minute verarbeiten. Das wird schnell teuer. Eine einfache Lösung besteht darin, jede Grafik nur einmal zu machen und dann eine Kopie davon an jeden Benutzer zu übergeben. Das Django-Web-Framework (auf dem Graphite aufgebaut ist) bietet einen hervorragenden Caching-Mechanismus, der verschiedene Backends wie memcached verwenden kann. Memcached 3 ist im Wesentlichen eine Hash-Tabelle als Netzdienst zur Verfügung gestellt. Clientanwendungen können Schlüsselwertepaare wie eine normale Hash-Tabelle abrufen und einstellen. Der Hauptvorteil der Verwendung von memcached besteht darin, dass das Ergebnis einer teuren Anforderung (wie das Rendern eines Graphen) sehr schnell gespeichert und später abgerufen werden kann, um nachfolgende Anforderungen zu bearbeiten. Um zu vermeiden, dass immer dieselben veralteten Graphen zurückgegeben werden, kann memcached so konfiguriert werden, dass die zwischengespeicherten Graphen nach einer kurzen Periode ablaufen. Auch wenn dies nur wenige Sekunden dauert, ist die Belastung, die es nimmt Graphite ist enorm, weil doppelte Anfragen so häufig sind. Ein weiterer häufiger Fall, der viele Rendering-Anforderungen erzeugt, ist, wenn ein Benutzer die Anzeigeoptionen optimiert und Funktionen in der Composer-Benutzeroberfläche anwendet. Jedes Mal, wenn der Benutzer etwas ändert, muss Graphite den Graphen neu zeichnen. Die gleichen Daten sind in jeder Anfrage beteiligt, so macht es Sinn, um die zugrunde liegenden Daten in den Memcache als gut. Dadurch wird die Benutzeroberfläche auf den Benutzer reagiert, da der Schritt zum Abrufen von Daten übersprungen wird. 7.6. Optimieren von IO Stellen Sie sich vor, Sie haben 60.000 Messwerte, die Sie an Ihren Graphite-Server senden, und jede dieser Metriken verfügt über einen Datenpunkt pro Minute. Denken Sie daran, dass jede Metrik ihre eigene Whisper-Datei auf dem Dateisystem hat. Dies bedeutet, dass Carbon eine Schreiboperation auf 60.000 verschiedene Dateien pro Minute durchführen muss. Solange Kohlenstoff jede Millisekunde auf eine Datei schreiben kann, sollte sie in der Lage sein, Schritt zu halten. Dies ist nicht zu weit geholt, aber lassen Sie uns sagen, Sie haben 600.000 Metriken Aktualisierung jede Minute oder Ihre Messwerte aktualisieren jede Sekunde oder vielleicht können Sie einfach nicht leisten, schnell genug Speicher. Was auch immer der Fall ist, nehmen Sie an, dass die Rate der eingehenden Datenpunkte die Rate der Schreiboperationen übersteigt, die Ihr Speicher aufrechterhalten kann. Wie sollte diese Situation behandelt werden Die meisten Festplatten haben in diesen Tagen langsame Suchzeit 4. das heißt, die Verzögerung zwischen dem Ausführen von IO-Operationen an zwei verschiedenen Standorten im Vergleich zu dem Schreiben einer zusammenhängenden Sequenz von Daten. Dies bedeutet, dass die angrenzende Schrift wir tun, desto mehr Durchsatz erhalten wir. Aber wenn wir haben Tausende von Dateien, die häufig geschrieben werden müssen, und jeder schreiben ist sehr klein (ein Flüstern Datenpunkt ist nur 12 Bytes) dann unsere Festplatten sind definitiv zu verbringen die meiste Zeit suchen. Unter der Annahme, dass die Rate der Schreiboperationen eine relativ niedrige Decke aufweist, ist die einzige Möglichkeit, unseren Datenpunktdurchsatz jenseits dieser Rate zu erhöhen, darin, mehrere Datenpunkte in einer einzigen Schreiboperation zu schreiben. Dies ist durchführbar, weil Flüstern aufeinanderfolgende Datenpunkte angrenzend auf der Platte angeordnet sind. So fügte ich eine updatemany Funktion hinzu, um zu flüstern. Die eine Liste von Datenpunkten für eine einzelne Metrik annimmt und zusammenhängende Datenpunkte in eine einzige Schreiboperation komprimiert. Obwohl dies jedes Schreiben grßer macht, ist der Zeitunterschied, um zehn Datenpunkte (120 Bytes) gegenüber einem Datenpunkt (12 Byte) zu schreiben, vernachlässigbar. Es dauert ziemlich viele Datenpunkte, bevor die Größe jedes Schreibens die Latenz merklich beeinflusst. Als nächstes habe ich einen Puffermechanismus in Kohlenstoff implementiert. Jeder ankommende Datenpunkt wird einer Warteschlange basierend auf seinem Metriknamen zugeordnet und dann an diese Warteschlange angehängt. Ein weiterer Thread wiederholt iteriert durch alle Warteschlangen und für jeden es zieht alle Datenpunkte aus und schreibt sie in die entsprechende Flüstern-Datei mit updatemany. Zurück zu unserem Beispiel, wenn wir 600.000 Metriken aktualisieren jede Minute und unsere Lagerung nur halten können mit 1 schreiben pro Millisekunde, dann die Warteschlangen werden am Ende hält etwa 10 Datenpunkte im Durchschnitt. Die einzige Ressource, die uns dies kostet, ist das Gedächtnis, das relativ reichlich ist, da jeder Datenpunkt nur wenige Bytes beträgt. Diese Strategie puffert dynamisch so viele Datenpunkte wie nötig, um eine Rate von eingehenden Datenpunkten aufrechtzuerhalten, die die Geschwindigkeit der IO-Operationen, die Ihr Speicher aufrechterhalten kann, übersteigen können. Ein guter Vorteil dieser Ansatz ist, dass es einen gewissen Grad an Elastizität, um temporäre IO Verlangsamungen zu behandeln. Wenn das System andere IO-Arbeiten außerhalb von Graphite ausführen muss, ist es wahrscheinlich, dass die Rate der Schreiboperationen abnimmt, wobei in diesem Fall die Kohlenstoff-Warteschlangen einfach wachsen werden. Je größer die Warteschlangen, desto größer die Schreibvorgänge. Da der Gesamtdurchsatz von Datenpunkten gleich der Rate der Schreiboperationen mal der durchschnittlichen Größe jedes Schreibens ist, ist Kohlenstoff in der Lage, aufrechtzuerhalten, solange genügend Speicher für die Warteschlangen vorhanden ist. Kohlenstoff-Warteschlangenmechanismus ist in Abbildung 7.4 dargestellt. Abbildung 7.4: Kohlenwasserstoff-Queuing-Mechanismus 7.7. Halten Sie es Echtzeit-Pufferung Datenpunkte war eine schöne Art und Weise zu optimieren Kohlenstoff-IO, aber es hat nicht lange gedauert, bis meine Nutzer eine ziemlich beunruhigende Nebenwirkung bemerken. Nachdem wir unser Beispiel nochmals besucht haben, haben wir 600.000 Messwerte, die jede Minute aktualisieren und davon ausgehen, dass unsere Lagerung nur mit 60.000 Schreiboperationen pro Minute aufrecht erhalten kann. Das bedeutet, dass wir ungefähr 10 Minuten Zeit haben werden, in denen Daten in Carbon-Warteschlangen sitzen. Für einen Benutzer bedeutet dies, dass die Graphen, die sie vom Graphite Webapp anfordern, die letzten 10 Minuten Daten fehlen: Nicht gut Zum Glück ist die Lösung ziemlich einfach. Ich habe einfach einen Socket-Listener auf Kohlenstoff, bietet eine Abfrage-Schnittstelle für den Zugriff auf die gepufferten Datenpunkte und dann ändert sich die Graphite Webapp zu verwenden diese Schnittstelle jedes Mal, wenn es benötigt, um Daten abzurufen. Der Webapp kombiniert dann die Datenpunkte, die er von Kohlenstoff mit den Datenpunkten, die er von der Platte und der Voila abgerufen hat, wieder, die Graphen sind in Echtzeit. Zugegeben, in unserem Beispiel werden die Datenpunkte auf die Minute und damit nicht genau in Echtzeit aktualisiert, aber die Tatsache, dass jeder Datenpunkt sofort in einem Graphen zugänglich ist, sobald er von Kohlenstoff empfangen wird, ist in Echtzeit. 7.8. Kernels, Caches und katastrophale Ausfälle Wie wahrscheinlich offensichtlich ist, ist ein wesentliches Merkmal der Systemleistung, dass Graphites eigene Leistung abhängt, IO-Latenz. Bisher wurde angenommen, dass unser System eine konstante niedrige IO-Latenzzeit von durchschnittlich etwa 1 Millisekunde pro Schreibvorgang aufweist, aber dies ist eine große Annahme, die eine etwas tiefere Analyse erfordert. Die meisten Festplatten einfach arent, dass schnell sogar mit Dutzenden von Platten in einem RAID-Array ist es sehr wahrscheinlich, mehr als 1 Millisekunde Latenz für zufälligen Zugriff sein. Doch wenn Sie versuchen, zu testen, wie schnell sogar ein alter Laptop ein ganzes Kilobyte auf die Festplatte schreiben könnte, würden Sie feststellen, dass der Schreibsystemaufruf in weit weniger als 1 Millisekunde zurückkehrt. Warum Immer wenn Software inkonsistente oder unerwartete Leistungsmerkmale aufweist, ist normalerweise entweder Pufferung oder Zwischenspeicherung schuld. In diesem Fall befassen sich beide mit beiden. Das Schreiben Systemaufruf doesnt technisch schreiben Sie Ihre Daten auf Festplatte, es legt es einfach in einen Puffer, die der Kernel schreibt dann auf Datenträger später. Deshalb kommt der Schreibaufruf normalerweise so schnell zurück. Selbst nachdem der Puffer auf die Festplatte geschrieben wurde, bleibt er häufig für nachfolgende Lesevorgänge im Cache. Beide Verhalten, Pufferung und Caching, erfordern Speicher natürlich. Kernel-Entwickler, die die intelligenten Leute, die sie sind, beschlossen, es wäre eine gute Idee, zu nutzen, was Benutzer-Speicherplatz ist derzeit kostenlos statt zuzuteilen Speicher direkt. Dies erweist sich als eine enorm nützliche Performance Booster und es erklärt auch, warum egal, wie viel Speicher Sie zu einem System hinzufügen, wird es in der Regel am Ende mit fast null freien Speicher nach einer bescheidenen Menge an IO. Wenn Ihre Benutzer-Raum-Anwendungen arent mit diesem Speicher dann Ihr Kernel wahrscheinlich ist. Der Nachteil dieses Ansatzes besteht darin, dass dieser freie Speicher aus dem Kernel entfernt werden kann, sobald eine Benutzer-Raum-Anwendung entscheidet, dass er mehr Speicher für sich selbst reservieren muss. Der Kernel hat keine andere Wahl, als ihn aufzugeben, verlieren, was Puffer dort gewesen sein können. Also, was bedeutet dies alles für Graphite Wir haben nur hervorgehoben Kohlenstoff s Vertrauen auf konsequent niedrige IO-Latenz und wir wissen auch, dass der Schreib-System-Aufruf nur schnell zurückgibt, weil die Daten nur in einen Puffer kopiert werden. Was passiert, wenn nicht genügend Speicher vorhanden ist, damit der Kernel die Pufferung von Schreibvorgängen fortsetzt. Die Schreibvorgänge werden synchron und damit schrecklich langsam. Dies führt zu einem dramatischen Abfall der Carbon-Schreiboperationen, wodurch Kohlenstoff-Warteschlangen wachsen, die noch mehr fressen Gedächtnis, Verhungern des Kernels noch weiter. Am Ende dieser Art von Situation führt in der Regel in Kohlenstoff läuft aus der Erinnerung oder wird von einem wütenden sysadmin getötet. Um diese Art von Katastrophe zu vermeiden, fügte ich mehrere Merkmale zu Kohlenstoff einschließlich konfigurierbarer Grenzen, wie viele Datenpunkte in die Warteschlange eingereiht werden und Raten-Grenzen auf, wie schnell verschiedene Flüster-Operationen durchgeführt werden können. Diese Eigenschaften schützen den Kohlenstoff vor Spiralen außer Kontrolle und verhängen stattdessen weniger raue Effekte wie das Fallenlassen einiger Datenpunkte oder das Verweigern, mehr Datenpunkte zu akzeptieren. Richtige Werte für diese Einstellungen sind jedoch systemspezifisch und erfordern eine angemessene Menge an zu testenden Tests. Sie sind nützlich, aber sie lösen das Problem nicht grundsätzlich. Dafür braucht es noch mehr Hardware. 7,9. Clustering Making mehrere Graphite-Server zu sein scheinen ein einziges System aus einer Benutzerperspektive ist nicht schrecklich schwierig, zumindest für eine naiumlve Umsetzung. Die Webapps-Benutzerinteraktion besteht im Wesentlichen aus zwei Operationen: Metrikfindung und Abruf von Datenpunkten (in der Regel in Form eines Graphen). Die Find - und Fetch-Operationen der Webapp werden in einer Bibliothek abgelegt, die ihre Implementierung von dem Rest der Codebase abstrahiert, und sie werden auch über HTTP-Request-Handler für einfache Remote-Aufrufe verfügbar gemacht. Die Suchoperation durchsucht das lokale Dateisystem von Flüsterdaten für Dinge, die mit einem benutzerdefinierten Muster übereinstimmen, genau wie ein Dateisystem glob wie. txt Dateien mit dieser Erweiterung übereinstimmt. Als eine Baumstruktur ist das Ergebnis, das von find zurückgegeben wird, eine Sammlung von Node-Objekten, die jeweils von den Branch - oder Leaf-Unterklassen von Node abgeleitet werden. Verzeichnisse entsprechen Zweigknoten und Flüsterdateien entsprechen Blattknoten. Diese Schicht der Abstraktion macht es einfach, verschiedene Arten von zugrunde liegenden Speicher, einschließlich RRD-Dateien 5 und gzipped Whisper-Dateien zu unterstützen. Die Leaf-Schnittstelle definiert eine Fetch-Methode, deren Implementierung vom Typ des Blattknotens abhängt. Im Fall von Whisper-Dateien ist es einfach eine dünne Wrapper um die Flüster-Bibliotheken eigene Fetch-Funktion. Wenn Clustering-Unterstützung hinzugefügt wurde, wurde die Suchfunktion erweitert, um Remote-Aufrufe über HTTP zu anderen Graphite-Servern, die in der Webapps-Konfiguration angegeben wurden, zu ermöglichen. Die in den Ergebnissen dieser HTTP-Aufrufe enthaltenen Knotendaten werden als RemoteNode-Objekte verpackt, die mit dem üblichen Knoten übereinstimmen. Ast. Und Leaf-Schnittstellen. Dies macht das Clustering transparent für den Rest der webapps-Codebasis. Die Fetch-Methode für einen entfernten Blattknoten wird als ein weiterer HTTP-Aufruf implementiert, um die Datenpunkte von dem Knoten Graphit-Server abzurufen. Alle diese Aufrufe werden auf die gleiche Weise ausgeführt, wie ein Client sie aufruft, mit Ausnahme eines zusätzlichen Parameters, der angibt, dass die Operation nur lokal ausgeführt und nicht im gesamten Cluster neu verteilt werden soll. Wenn der Webapp gefragt wird, einen Graphen zu rendern, führt er den Suchvorgang aus, um die angeforderten Metriken zu lokalisieren, und ruft jeweils Abruf ab, um ihre Datenpunkte abzurufen. Dies funktioniert, ob sich die Daten auf dem lokalen Server, Remote-Servern oder beiden befinden. Wenn ein Server heruntergefahren wird, wird das Fernabrufe-Zeitlimit ziemlich schnell und der Server wird für eine kurze Zeit als außer Betrieb gesetzt, während der keine weiteren Anrufe getätigt werden. Vom Standpunkt des Benutzers aus, werden alle Daten auf dem verlorenen Server in ihren Graphen fehlen, es sei denn, dass Daten auf einem anderen Server im Cluster dupliziert werden. 7.9.1. Eine kurze Analyse der Clustering-Effizienz Der teuerste Teil einer grafischen Anforderung ist die grafische Darstellung. Jedes Rendering wird von einem einzelnen Server ausgeführt, so dass mehr Server hinzugefügt werden, wodurch die Kapazität für die Darstellung von Graphen effektiv erhöht wird. Jedoch bedeutet die Tatsache, dass viele Anfragen am Ende verteilen, Anrufe zu jedem anderen Server im Cluster verteilen, dass unser Clustering-Schema einen Großteil der Front-End-Last aufteilt, anstatt es zu verteilen. Was wir an dieser Stelle erreicht haben, ist jedoch ein effektiver Weg, um Back-End-Last zu verteilen, da jede Kohlenstoffinstanz unabhängig arbeitet. Dies ist ein guter erster Schritt, da die meiste Zeit das Backend ist ein Engpass weit vor dem vorderen Ende ist, aber deutlich das Vorderende wird nicht horizontal skaliert mit diesem Ansatz. Um die Front-End-Skala effektiver zu gestalten, muss die Anzahl der von der Webapp durchgeführten Remote-Find-Aufrufe reduziert werden. Auch hier ist die einfachste Lösung Caching. So wie memcached bereits zum Cache von Datenpunkten und gerenderten Graphen verwendet wird, kann es auch verwendet werden, um die Ergebnisse von Suchaufträgen zwischenzuspeichern. Da der Standort von Metriken viel seltener ist, sich häufig zu ändern, sollte dieser typischerweise länger zwischengespeichert werden. Der Trade-off des Setzen des Cache-Timeouts für die Ergebnise zu lange ist jedoch, dass neue Metriken, die der Hierarchie hinzugefügt wurden, möglicherweise nicht so schnell für den Benutzer angezeigt werden. 7.9.2. Verteilen von Metriken in einem Cluster Der Graphite-Webapp ist in einem Cluster ziemlich homogen, da er genau denselben Job auf jedem Server ausführt. Carbon s Rolle kann jedoch von Server zu Server je nachdem, welche Daten Sie wählen, um jede Instanz zu senden variieren. Oft gibt es viele verschiedene Clients senden Daten an Kohlenstoff. So wäre es ziemlich lästig, jeden Client-Konfiguration mit Ihrem Graphite-Cluster Layout zu koppeln. Anwendungsmetriken können zu einem Carbon-Server gehen, während Business-Metriken möglicherweise an mehrere Carbon-Server zur Redundanz gesendet werden. Zur Vereinfachung der Verwaltung von Szenarien wie diesem, kommt Graphite mit einem zusätzlichen Tool namens Kohlenstoff-Relais. Seine Aufgabe ist ganz einfach, dass es metrische Daten von Clients genau wie die Standard-Carbon-Daemon (die eigentlich Carbon-Cache genannt wird), sondern statt der Speicherung der Daten, gibt es eine Reihe von Regeln, um die Metrik-Namen zu bestimmen, welche Carbon-Cache-Servern Um die Daten an. Jede Regel besteht aus einem regulären Ausdruck und einer Liste von Zielservern. Für jeden empfangenen Datenpunkt werden die Regeln in der Reihenfolge ausgewertet, und die erste Regel, deren regulärer Ausdruck mit dem Metriknamen übereinstimmt, wird verwendet. Auf diese Weise alle Kunden müssen tun, senden ihre Daten an die Carbon-Relais und es wird am Ende auf den richtigen Servern. In gewissem Sinne Carbon-Relais bietet Replikation-Funktionalität, obwohl es genauer gesagt werden Eingabe-Duplizierung, da es nicht mit Synchronisierungsproblemen. Wenn ein Server vorübergehend untergeht, fehlen die Datenpunkte für den Zeitraum, in dem es heruntergefahren wurde, aber ansonsten normal funktionieren. Es gibt administrative Skripts, die die Kontrolle über den Re-Synchronisationsprozeß in den Händen des Systemadministrators überlassen. 7.10. Design-Reflexionen Meine Erfahrung in der Arbeit an Graphite hat bekräftigt ein Glaube von mir, dass Skalierbarkeit hat sehr wenig mit Low-Level-Performance zu tun, sondern ist ein Produkt des gesamten Designs. Ich habe in viele Engpässe auf dem Weg, aber jedes Mal, wenn ich für Verbesserungen in der Konstruktion und nicht beschleunigt in der Leistung. Ich wurde oft gefragt, warum ich Graphite in Python anstelle von Java oder C geschrieben habe, und meine Antwort ist immer, dass ich noch über eine wahre Notwendigkeit für die Leistung kommen, die eine andere Sprache anbieten könnte. In Knu74, Donald Knuth berühmt gesagt, dass vorzeitige Optimierung ist die Wurzel allen Übels. Solange wir davon ausgehen, dass unser Code in nicht-trivialer Weise weiterentwickelt wird, ist jede Optimierung 6 in gewisser Weise vorzeitig. Einer der größten Stärken und größten Schwächen Graphits ist die Tatsache, dass nur sehr wenig davon im herkömmlichen Sinne entworfen wurde. Im Großen und Ganzen entwickelte sich Graphit allmählich, Hürde durch Hürde, als Probleme entstanden. Viele Male waren die Hürden vorhersehbar und verschiedene präventive Lösungen schienen natürlich. Allerdings kann es nützlich sein, zu vermeiden, Probleme zu lösen, die Sie eigentlich noch nicht haben, auch wenn es wahrscheinlich scheint, dass Sie bald. Der Grund dafür ist, dass man viel mehr lernen kann, wenn man die tatsächlichen Misserfolge genau studiert, als die Theorie über bessere Strategien. Die Problemlösung wird sowohl durch die empirischen Daten, die wir haben, als auch durch unser eigenes Wissen und unsere Intuition bestimmt. Ive festgestellt, dass das Zweifeln an Ihrer eigenen Weisheit genügend kann Sie zwingen, um Ihre empirischen Daten gründlicher zu betrachten. Zum Beispiel, wenn ich zum ersten Mal schrieb Flüstern war ich davon überzeugt, dass es in C für Geschwindigkeit umgeschrieben werden müssen und dass meine Python-Implementierung nur als Prototyp dienen würde. Wenn ich werent unter einer Zeit-Crunch Ich sehr gut kann die Python-Implementierung komplett übersprungen haben. Es stellt sich heraus, dass IO ist ein Engpass so viel früher als CPU, dass die geringere Effizienz von Python kaum zählt überhaupt in der Praxis. Wie ich schon sagte, ist der evolutionäre Ansatz auch eine große Schwäche von Graphit. Schnittstellen, stellt sich heraus, eignet sich nicht gut für die allmähliche Evolution. Eine gute Schnittstelle ist konsistent und setzt Konventionen ein, um die Vorhersagbarkeit zu maximieren. Durch diese Maßnahme, Graphites URL-API ist derzeit eine Sub-Par-Schnittstelle meiner Meinung nach. Optionen und Funktionen sind im Laufe der Zeit angeheftet worden, manchmal bilden kleine Inseln der Konsistenz, aber insgesamt fehlt ein globales Gefühl der Konsistenz. Der einzige Weg, um ein solches Problem zu lösen ist durch die Versionierung von Schnittstellen, aber das hat auch Nachteile. Sobald eine neue Schnittstelle entworfen ist, ist die alte ist immer noch schwer loszuwerden, verweilen als evolutionäre Gepäck wie die menschliche Anhang. Es scheint harmlos genug, bis eines Tages Ihr Code Appendizitis (d. H. Ein Bug gebunden an die alte Schnittstelle) und youre gezwungen, zu betreiben. Wenn ich früher einmal etwas über Graphite ändern sollte, wäre es gewesen, viel größere Sorgfalt beim Entwerfen der externen APIs zu nehmen, indem ich nachdenken würde, anstatt sie nach und nach zu entwickeln. Ein weiterer Aspekt von Graphite, der einige Frustration verursacht, ist die begrenzte Flexibilität des hierarchischen metrischen Namensmodells. Während es ist ganz einfach und sehr praktisch für die meisten Anwendungsfälle, macht es einige anspruchsvolle Abfragen sehr schwierig, sogar unmöglich, auszudrücken. Wenn ich zuerst an die Erstellung von Graphit wusste, wusste ich von Anfang an, dass ich eine menschlich editierbare URL-API für die Erstellung von Graphen 7 wünschte. Während Im noch froh, dass Graphit dies heute bereitstellt, Im Angst, diese Anforderung hat die API mit übermäßig einfacher Syntax belastet Macht komplexe Ausdrücke unhandlich. Eine Hierarchie macht das Problem, den Primärschlüssel für eine Metrik ganz einfach zu bestimmen, weil ein Pfad im Wesentlichen ein Primärschlüssel für einen Knoten im Baum ist. Der Nachteil ist, dass alle beschreibenden Daten (d. h. Spaltendaten) direkt in den Pfad eingebettet sein müssen. Eine mögliche Lösung besteht darin, das hierarchische Modell zu pflegen und eine separate Metadaten-Datenbank hinzuzufügen, um eine erweiterte Auswahl von Metriken mit einer speziellen Syntax zu ermöglichen. 7.11. Opening Source Mit Blick auf die Entwicklung von Graphite bin ich immer noch überrascht, wie weit es als Projekt gekommen ist und wie weit es mich als Programmierer genommen hat. Es begann als Haustier-Projekt, das nur ein paar hundert Zeilen Code war. Die Rendering-Engine begann als Experiment, einfach zu sehen, ob ich einen schreiben konnte. Whisper wurde im Laufe eines Wochenendes aus der Verzweiflung geschrieben, um ein Show-Stopper-Problem vor einem kritischen Starttermin zu lösen. Kohlenstoff wurde mehrmals umgeschrieben, als ich mich erinnere. Sobald ich erlaubte, Graphit unter einer Open-Source-Lizenz 2008 freizugeben, habe ich nie wirklich viel Antwort erwartet. Nach ein paar Monaten wurde es in einem CNET-Artikel erwähnt, der von Slashdot abgeholt wurde und das Projekt plötzlich begann und seitdem aktiv ist. Heute gibt es Dutzende von großen und mittelständischen Unternehmen mit Graphit. Die Gemeinschaft ist sehr aktiv und wächst weiter. Weit davon entfernt, ein fertiges Produkt, gibt es eine Menge von kühlen experimentellen Arbeit getan, die es Spaß macht, zu arbeiten und voller Potenzial. Launchpad. netgraphite Es gibt einen anderen Port, über den serialisierte Objekte gesendet werden können, was effizienter ist als das reine Textformat. Dies wird nur bei sehr hohem Verkehrsaufkommen benötigt. Memcached. org Solid-State-Laufwerke haben im Allgemeinen extrem schnelle Suchzeiten im Vergleich zu herkömmlichen Festplatten. RRD-Dateien sind tatsächlich Zweigknoten, da sie mehrere Datenquellen enthalten können. Eine RRD-Datenquelle ist ein Blattknoten. Knuth spezifisch bedeutet Low-Level-Code-Optimierung, nicht makroskopische Optimierung wie Design-Verbesserungen. Dies zwingt die Grafiken selbst zu open source. Jeder kann einfach auf eine grafische URL zu verstehen oder zu ändern it. R.R. Donnelley Sons Company Aktienkurse Zusammenfassung Daten Echtzeit-After-Hours Pre-Market News Flash Zitat Zusammenfassung Zitat Interaktive Charts Standardeinstellung Bitte beachten Sie, dass, sobald Sie Ihre Auswahl treffen, es gilt für alle zukünftigen Besuche NASDAQ gelten. Wenn Sie zu einem beliebigen Zeitpunkt daran interessiert sind, auf die Standardeinstellungen zurückzukehren, wählen Sie bitte die Standardeinstellung oben. Wenn Sie Fragen haben oder Probleme beim Ändern Ihrer Standardeinstellungen haben, senden Sie bitte eine E-Mail an isfeedbacknasdaq. Bitte bestätigen Sie Ihre Auswahl: Sie haben ausgewählt, Ihre Standardeinstellung für die Angebotssuche zu ändern. Dies ist nun Ihre Standardzielseite, wenn Sie Ihre Konfiguration nicht erneut ändern oder Cookies löschen. Sind Sie sicher, dass Sie Ihre Einstellungen ändern möchten, haben wir einen Gefallen zu bitten Bitte deaktivieren Sie Ihren Anzeigenblocker (oder aktualisieren Sie Ihre Einstellungen, um sicherzustellen, dass Javascript und Cookies aktiviert sind), damit wir Sie weiterhin mit den erstklassigen Marktnachrichten versorgen können Und Daten, die Sie von uns erwarten.

No comments:

Post a Comment