Veröffentlichungsdatum: 1. März 2020
Distributed Tracing bzw. Distributed Request Tracing ist eine Methode zum Monitoring von Anwendungen, die auf einer Microservices-Architektur aufsetzen.
IT- und DevOps-Teams nutzen Distributed Tracing, um den Verlauf einer Anfrage oder Transaktion zu verfolgen, wenn sie die Anwendung durchläuft, die kontrolliert werden soll. So lassen sich Engpässe, Fehler und andere Probleme erkennen, die sich auf die Anwendungsleistung auswirken können.
Tracing ist ein elementares Verfahren der Software-Entwicklung. Programmierer nutzen es zusammen mit anderen Logging-Methoden, wenn sie herausfinden wollen, wie sich eine Anwendung konkret verhält. Das übliche Tracing stößt jedoch beim Troubleshooting von Anwendungen in verteilten Software-Architekturen an seine Grenzen. Weil Microservices unabhängig voneinander skalieren, ist es gängige Praxis, einzelne Services in mehreren Iterationen auszuführen, auf unterschiedlichen Servern, an unterschiedlichen Standorten und in unterschiedlichen Umgebungen. Jede Anfrage durchläuft also ein derart komplexes Netz, dass es nahezu unmöglich ist, sie mit den klassischen Verfahren nachzuverfolgen, die auf Anwendungen mit nur einem einzigen Service ausgelegt sind.
Distributed Tracing löst dieses Problem – und noch eine ganze Menge anderer Performance-Probleme. Distributed Tracing kann Anfragen durch jeden Service und jedes Modul verfolgen und liefert einen Bericht, der den Ablauf einer Anfrage von Anfang bis Ende verzeichnet. Analysten, SREs, Entwickler etc. können damit jede Iteration einer Funktion nachvollziehen. Auf diese Weise wird ein Performance-Monitoring möglich, das direkt sichtbar macht, welche Instanz der betreffenden Funktion die App ausbremst oder abstürzen lässt – und wie der Fehler zu beheben ist.
Im Folgenden wollen wir uns Distributed Tracing genauer ansehen – und die Technologien, die ein solches Tracing in Ihrem Unternehmen ermöglichen.
Die Funktionsweise von Distributed Tracing lässt sich am besten erklären, wenn man sich den Umgang mit einer einzelnen Anfrage ansieht: Das Tracing beginnt in dem Moment, in dem ein Endnutzer mit der Anwendung interagiert. Wenn der Benutzer eine erste Anfrage sendet – nehmen wir als gängiges Beispiel eine HTTP-Anfrage – wird ihr eine eindeutige Trace-ID zugewiesen. Wenn sich die Anfrage durch das Host-System bewegt, wird jede betreffende Operation („Span“ oder „Child Span“ genannt) mit der Trace-ID dieser ersten Anfrage gekennzeichnet und bekommt zusätzlich eine eigene, eindeutige ID zugewiesen, plus die ID der Operation, die die aktuelle Anfrage ursprünglich generiert hat („Parent Span“ genannt).
Jeder Span stellt einen einzelnen Schritt auf dem Weg der Anfrage dar; dabei werden wichtige Daten bezüglich des Microservices codiert, der diese Operation ausführt. Zu diesen Daten gehören:
- der Name des Services und die Adresse des Prozesses, der die Anfrage verarbeitet,
- Logs und Events, die zum Kontext der Prozessaktivität gehören,
- Tags für die Abfrage und Filterung von Anfragen nach Session-ID, Datenbank-Host, HTTP-Methode und anderen Identifikationsmerkmalen sowie
- detaillierte Stack Traces und Fehlermeldungen bei Ausfällen.
Tools für Distributed Tracing wie Zipkin oder Jaeger (wir werden uns beide unten genauer ansehen) können die Daten aller Spans korrelieren, formatieren und visualisieren, sodass sie bei Bedarf auf einer Web-Oberfläche zur Verfügung stehen.
Jetzt stellen Sie sich einmal ein beliebtes Online-Videospiel vor, das von Millionen gespielt wird – der Inbegriff einer modernen Microservices-Anwendung. Hier müssen der Standort jedes Players, jede Interaktion mit anderen Spielern und der Umgebung, jeder Gegenstand, den ein Spieler erwirbt, die Uhrzeit des Spielendes und noch eine Vielzahl anderer Daten im Game verfolgt werden. Einen reibungslosen Spielbetrieb mit herkömmlichen Tracing-Methoden aufrechtzuerhalten, wäre undenkbar. Aber Distributed Request Tracing macht genau das möglich.
Der Hauptvorteil von Distributed Tracing besteht darin, dass es eine kohärente Sicht auf verteilte Systeme ermöglicht, was wiederum eine Vielzahl weiterer Vorteile mit sich bringt:
- Gesteigerte Produktivität: Weil Microservice-Architekturen, anders als monolithische Anwendungen, verteilte Architekturen sind, werden Performance-Monitoring-Funktionen wie das Identifizieren und Beheben von Problemen oft zeitaufwendig und teuer. Hinzu kommt, dass Ausfalldaten bei Microservices nicht immer klar und verständlich geliefert werden, sodass Entwickler bei der Problemsuche oft erst Fehlermeldungen und obskure Statuscodes enträtseln müssen. Distributed Tracing bietet eine umfassendere Sicht auf verteilte Systeme und ermöglicht Entwicklern dadurch eine schnellere Diagnose und Behebung von gescheiterten Anfragen. Außerdem lassen sich die Ursachen von Fehlern damit effizienter feststellen und beheben.
- Bessere teamübergreifende Zusammenarbeit: In einer Microservice-Umgebung wird jeder Prozess von einem eigenen Team entwickelt, das auf die Technologie spezialisiert ist, die der jeweilige Service verwendet. Das führt zu Problemen, wenn es darum geht, festzustellen, wo ein Fehler aufgetreten ist und wer für die Behebung verantwortlich ist. Distributed Tracing trägt dazu bei, diese Datensilos, die damit verbundenen Produktivitätsengpässe und andere Performance-Probleme aufzulösen, verkürzt gleichzeitig die Reaktionszeiten und ermöglicht eine effizientere Zusammenarbeit der Teams.
- Flexible Implementierung: Distributed-Tracing-Tools können mit vielen verschiedenen Anwendungen und Programmiersprachen zum Einsatz kommen, sodass Entwickler sie in praktisch jedes Microservices-System einbinden und sich die Daten in einer einzigen Tracing-Anwendung anzeigen lassen können.
- Code-Tracing: Beim Code-Tracing interpretiert ein Programmierer die Ergebnisse jeder Codezeile einer Anwendung und zeichnet die Auswirkungen per Hand auf (also nicht mit einem Debugger, der den Prozess automatisiert), um so die Programmausführung nachzuverfolgen. Das manuelle Tracing kleiner Codeblöcke kann durchaus effizienter sein, da der Programmierer dann nicht das gesamte Programm ausführen muss, um die Auswirkungen kleiner Änderungen zu prüfen.
- Daten-Tracing: Daten-Tracing hilft dabei, die Genauigkeit und Qualität kritischer Datenelemente zu überprüfen, sie zu ihren Quellsystemen zurückzuverfolgen und sie mit statistischen Methoden zu überwachen und zu verwalten. Normalerweise besteht die beste Methode der Genauigkeitsüberprüfung darin, Operationen bis zu ihrem Ursprung zurückzuverfolgen und mithilfe von Quelldaten zu validieren – dies hat sich in der Vergangenheit jedoch bei umfangreichen operativen Prozessen als nicht kosteneffizient erwiesen. Stattdessen wird oft die statistische Prozesslenkung (Statistical Process Control, SPC) für Priorisierung, Tracing, Monitoring und Kontrolle von kritischen Datenelementen genutzt.
- Programm-Trace (ptrace): Ein Programm-Trace ist ein Index der ausgeführten Anweisungen und der referenzierten Daten während der Ausführung einer Anwendung. Zu den Informationen in einem Programm-Trace gehören unter anderem der Programmname, die Sprache und die ausgeführte Quellanweisung. Programm-Traces werden beim Debugging einer Anwendung verwendet.
In diesem Zusammenhang versteht man unter zentralem Logging das Aggregieren von Daten aus einzelnen Microservices an einem zentralen Ort, um den Zugriff und die Analyse zu erleichtern.
Eine der mühseligsten, aber wichtigsten Aufgaben von Entwicklern besteht darin, die Log-Dateien einer Anwendung zu durchsuchen, um Fehler zu finden, die ein Problem verursachen oder dazu beitragen. In Microservices-Umgebungen kann dies ganz besonders mühsam sein.
Wie gesagt sind herkömmliche Monitoring-Methoden gut für monolithische Anwendungen geeignet, da man nur eine einzige Codebasis überwacht. Es liegt daher nahe, dieselben Methoden auch auf eine Microservice-Architektur anzuwenden, indem man jeden Microservice als kleinen Monolith betrachtet und seine Anwendungs- und Systemlogs zur Problemdiagnose heranzieht. Das Problem bei diesem Ansatz ist jedoch, dass nur Daten für diesen einzelnen Service erfasst werden und nur Probleme bei diesem speziellen Prozess behoben werden können, wodurch sich die Reaktionszeit verlängert.
Beim zentralen Logging werden daher Logs aus mehreren Services an einem zentralen Ort erfasst und aggregiert, wo sie dann in einer Datenbank indiziert werden. Die Log-Daten können anhand von Feldern wie Status, Host, Schweregrad, Ursprung und Zeitstempel in der Log-Management-Software durchsucht, gefiltert und gruppiert werden.
Das zentrale Logging bietet bei verteilten Systemen eine Reihe von Vorteilen. Da sich alle relevanten Logs an einem Ort befinden, müssen Entwickler deutlich weniger Zeit und Arbeit aufwenden, um die Kernursache eines Anwendungsproblems zu identifizieren. Da die Logs zudem in Form aussagekräftiger Daten und nicht nur als Text vorliegen, sind spezifischere, komplexere Abfragen möglich, und es entsteht ein deutlicheres Bild der Systemleistung als Ganzen.
Beim Distributed Logging (verteilten Logging) werden die Log-Dateien nicht an einem zentralen Ort zusammengeführt, sondern dezentral aufbewahrt. Es gibt gute Gründe, dies dem zentralen Logging vorzuziehen.
Zum einen kann die Übertragung von Logs über ein Netzwerk an einen zentralen Ort eine Menge Bandbreite kosten. Abhängig von Ihrem Netzwerk sowie der Anzahl und Häufigkeit der generierten Logs könnten so beim Zentralisieren der Logs Konflikte mit wichtigeren Anwendungen und Prozessen entstehen. Zudem arbeiten manche Log-Speichersysteme zuverlässiger, wenn sie sich in der Nähe des Geräts befinden, das die Log-Dateien erzeugt.
Auch bei umfangreichen Systemen ist verteiltes Logging unter Umständen besser geeignet. Anwendungen mit vielen Microservices erzeugen von Haus aus viele Log-Meldungen, was zentrales Logging schwerfälliger und weniger kosteneffizient macht.
Für Microservices-Logging gibt es eine Reihe von Best Practices, die der losen Koppelung und der modularen Struktur von Microservice-Architekturen gerecht werden. Das Ziel besteht darin, das System kohärenter zu machen, um die Effizienz und Genauigkeit von Troubleshooting und Debugging zu verbessern.
Zu Microservices-Logging gehören in der Regel die folgenden Vorgehensweisen:
- Anfragen korrelieren: Um eine Anfrage zu erfüllen, interagiert jeder Service in einem Microservice-System mit anderen Services. Wird die anfängliche Anfrage mit einer eindeutigen ID gekennzeichnet, können Sie sie leicht durch das System verfolgen, mögliche Fehler erkennen und feststellen, ob diese von der vorherigen Serviceanfrage oder der nächsten verursacht wurden. Ein Entwickler kann diese eindeutige ID in die Such-Engine des Log-Aggregators eingeben, um die Logs aus allen Services zu Analysezwecken abzurufen.
- Informationen loggen: Mehr Log-Daten bedeuten mehr Kontext und damit ein besseres Verständnis des Problems. Der Name des Services, der die Log-Meldung erzeugt, die Korrelations-ID, die IP-Adressen des Servers und des Clients, von dem die Anfrage stammt, sowie Datum und Uhrzeit, zu denen die Meldung gesendet und empfangen wurde, sind nur einige der Datenpunkte, die Sie in Ihren Logs erfassen sollten.
- Log-Daten strukturieren: Microservice-Architekturen haben unter anderem den Vorteil, dass man verschiedene Technologie-Stacks verwenden kann. Dies führt allerdings auch zu zahlreichen verschiedenen Log-Formaten, was bei der Analyse oft eine enorme Herausforderung darstellt. Wenn diese Daten in einem Standardformat wie JSON (JavaScript Object Notation) ausgegeben werden, kann man sie leichter analysieren und von einem zentralen Ort aus nach einer Vielzahl von Feldern durchsuchen.
- Logs zentralisieren: Das Abrufen und Korrelieren der Logs von einzelnen Servern kostet wertvolle Zeit und Energie – ein Aufwand, der mit der Anzahl der Mikrosysteme exponentiell steigt. Zentralisiertes Logging löst dieses Problem. Zudem stehen die betreffenden Logs bei verteiltem Logging nicht mehr zur Verfügung, wenn die Ausführung eines Servers oder Containers ohne Vorwarnung abbricht. Bei zentralisiertem Logging werden die Logs alle paar Minuten an ein zentrales Repository übermittelt, sodass unwiederbringliche Datenverluste vermieden werden.
OpenTracing und OpenCensus waren bisher konkurrierende Open-Source-Projekte für verteiltes Tracing. Vor Kurzem wurden sie in einem einzigen Tool namens OpenTelemetry zusammengeführt.
Das von der Cloud Native Computing Foundation (CNCF) betreute OpenTracing stellt eine standardisierte Tracing-API bereit, sodass Entwickler die Instrumentierung in häufig verwendete Bibliotheken oder ihren eigenen Code einbetten können, ohne sich an einen bestimmten Anbieter zu binden. Das bietet zwar die gewünschte Flexibilität, aber weil die API ausschließlich auf das Tracing fokussiert, ist sie nur von begrenztem Nutzen und wird von Entwicklern und Anbietern auch nicht einheitlich implementiert.
OpenCensus war ursprünglich eine Google-Entwicklung auf Basis der internen Tracing-Plattform. Seit der Freigabe als Open-Source-Projekt nehmen nun auch Microsoft sowie andere Anbieter und Förderer Einfluss auf die Richtung des Standards. OpenCensus umfasst eine Reihe mehrsprachiger Bibliotheken, die Metriken zum Anwendungsverhalten sammeln und diese Daten dann an die vom Entwickler gewählte Analyseplattform im Backend übertragen. Außerdem kann OpenCensus Meldungen, Anfragen und Services von ihrer Quelle bis zum Ziel verfolgen. Da es keine API für die Code-Einbettung von OpenCensus gab, verwendeten Entwickler für diese Aufgabe von der Community erstellte automatische Instrumentierungsagenten.
Das ebenfalls von der CNCF betreute OpenTelemetry führt die Codebasen von OpenTracing und OpenCensus zusammen und kombiniert so ihre jeweiligen Stärken. OpenTelemetry (derzeit im Beta-Stadium) bietet „eine Sammlung von APIs, Bibliotheken, Agenten und Datenkollektorservices“ zur Erfassung verteilter Anwendungstraces und -metriken, die mit gängigen Observability-Tools analysiert werden können. OpenTelemetry hat zudem vor, in absehbarer Zeit die bestehenden Möglichkeiten der Datenerfassung um Logging-Funktionen zu erweitern.
Jaeger and Zipkin are two popular open-source request tracing tools, each with similar components: a collector, datastore, query API, and web user interface. Outgoing requests are traced along with the application. The collector then records and correlates the data between different traces and sends it to a database where it can be queried and analyzed through the UI.
Jaegar and Zipkin are differentiated by their architecture and programming language support — Jaeger is implemented in Go and Zipkin in Java. Zipkin supports virtually every programming language with dedicated libraries for Java, Javascript, C, C++, C#, Python, Go, Scala, and others. Jaeger’s supported-language list is shorter: C#, Java, Node.js, Python, and Go.
AWS X-Ray ist das native Distributed-Tracing-Tool von Amazon Web Services (AWS). Als größter Cloud-Anbieter der Welt ist Amazon am Wandel von monolithischen Anwendungen zu Microservice-Apps maßgeblich beteiligt und hat daher ein eigenes Tracing-Tool entwickelt.
Wie vergleichbare Tools verfolgt AWS X-Ray den Weg von Benutzeranfragen durch eine Anwendung und sammelt dabei Daten, die zum Identifizieren der Ursachen von Latenzproblemen, Fehlern und anderen Hindernissen beitragen können. Diese Trace-Daten werden formatiert in einer Service Map bereitgestellt, die Entwickler parsen können, um Probleme zu lokalisieren und zu identifizieren.
AWS X-Ray kann natürlich problemlos mit anderen Amazon-Services wie AWS Lambda, Amazon EC2 (Elastic Compute Cloud), Amazon EC2 Container Service (Amazon ECS) und AWS Elastic Beanstalk verwendet werden. Es kann sowohl in der Erstellungs- als auch der Testphase einer Anwendung sowie zur Wartung der App in der Produktion eingesetzt werden.
Kafka ist eine verteilte Plattform mit hohem Durchsatz und geringer Latenz für Echtzeit-Datenfeeds, die häufig in Microservice-Architekturen eingesetzt wird. Man kann damit Datensatzströme in Echtzeit verarbeiten, sie nach dem Prinzip einer Nachrichtenwarteschlange veröffentlichen und abonnieren sowie „auf eine fehlertolerante, dauerhafte Weise“ speichern.
Kafka nutzt zum Abstrahieren von Datensatzströmen sogenannte Topics. Das sind Kategorie- oder Feed-Namen, unter denen die Datensätze veröffentlicht werden. Für jedes Topic legt Kafka ein partitioniertes Log an, bei dem es sich um eine geordnete, laufend erweiterte Abfolge von Datensätzen handelt, das als externes Commit-Log für ein verteiltes System dienen kann.
Neben Splunk gibt es beispielsweise folgende Tools für Log-Aggregation und -Monitoring, die in der Regel jedoch ein geringeres Leistungsspektrum umfassen:
Elastic (ehemals ELK: Elasticsearch, Logstash, Kibana): Elastic ist ein Stack für verteilte Systeme und vereint die drei Tools Logstash, Elasticsearch und Kibana. Logstash aggregiert Log-Dateien; mit Elasticsearch können Daten indiziert und durchsucht werden; Kibana stellt ein Dashboard für die Datenvisualisierung bereit. Elastic ist Open Source und kostenlos. Man kann den gesamten Stack oder die Tools einzeln nutzen.
Loggly: Dieses in der Cloud gehostete Tool für Log-Management und -Analyse wurde von DevOps-Nutzern für DevOps-Nutzer entwickelt. Es ist darauf ausgelegt, große Mengen an Log-Daten über eine intuitiv zu bedienende Schnittstelle auszuwerten, und wird hauptsächlich für Troubleshooting und Kundensupport verwendet. Zudem umfasst Loggly eine REST-API, mit der es in andere Tools integriert werden kann.
PaperTrail: PaperTrail dient nicht dazu, Logs zu aggregieren, sondern bietet Endanwendern eine einfache Möglichkeit, bereits gesammelte Logs zu durchsuchen. Es lässt sich leicht installieren und hat eine klar aufgebaute Oberfläche, die Ihnen eine konsolidierte Sicht auf die Daten aus einem Browser, der Befehlszeile oder einer API bietet.
Graylog: Graylog ist ebenfalls ein Open-Source-Tool zur Log-Analyse. Es ist speziell dafür konzipiert, Entwicklern dabei zu helfen, Fehler in ihren Anwendungen zu finden und zu beheben. Seine einfache Benutzeroberfläche arbeitet schnell und kann eine breite Palette von Datenformaten verarbeiten.
Distributed Tracing ist bei verteilten Apps unerlässlich
Die Vorteile von Microservices bei der Erstellung von Cloud-Anwendungen sind hinlänglich bekannt, und es sieht nicht so aus, als würde dieser Trend nachlassen. Angesichts der zunehmenden Komplexität derartiger Systeme bietet Distributed Request Tracing einen enormen Vorteil gegenüber dem älteren Suchansatz (der sprichwörtlichen Suche nach der Nadel im Heuhaufen) beim Aufspüren von Problemen, die Ihre Services stören könnten. Wenn Sie für ein Microservice-System verantwortlich sind, wird Ihnen die Einführung dieses leistungsfähigen Tools in Ihrem Unternehmen die Arbeit enorm erleichtern.
Wie funktioniert Distributed Tracing?
Welche Vorteile hat Distributed Tracing?
Welche Arten von Tracing-Tools gibt es?
Wie funktioniert Microservices-Logging?
Welche Standards gibt es für Open Distributed Tracing (OpenTracing, OpenCensus, OpenTelemetry)?
Was ist Jaeger und Zipkin Tracing?
Welche Tools für Log-Aggregation und -Monitoring gibt es?
Fazit: Distributed Tracing ist bei verteilten Apps unerlässlich
Die 5 grundlegenden DevOps-Praktiken
Was unterscheidet erfolgreiche DevOps-Teams von denen, die scheitern? Ganz einfach: Diese 5 grundlegenden Praktiken.