Bearbeiten

Freigeben über


Überwachen eines verteilten Systems mithilfe von Application Insights und OpenCensus

Azure Event Hubs
Azure-Funktionen
Azure-Servicebus
Azure Monitor

In diesem Artikel wird ein verteiltes System beschrieben, das mit Azure Functions, Azure Event Hubs und Azure Service Bus erstellt wird. Details hinsichtlich der Überwachung des End-to-End-Systems mithilfe von OpenCensus für Python und Application Insights werden verdeutlicht. In diesem Artikel wird auch die verteilte Ablaufverfolgung vorgestellt und die Funktionsweise anhand von Python-Codebeispielen erläutert. Das fiktive Unternehmen Contoso wird in der Architektur verwendet, um das Szenario zu beschreiben.

Hinweis

OpenCensus und OpenTelemetry werden zusammengeführt; OpenCensus bleibt jedoch weiterhin das empfohlene Tool zur Überwachung von Azure Functions. OpenTelemetry für Azure befindet sich in der Vorschauversion, daher sind einige Funktionen noch nicht verfügbar.

Aufbau

Diagramm mit der implementierten Architektur, die in drei Schritte unterteilt ist: Query, Process und Upsert.

Laden Sie eine Visio-Datei dieser Architektur herunter.

Workflow

  1. Abfrage Eine vom Timer ausgelöste Azure-Funktion fragt die interne Contoso-API ab, um einmal täglich die neuesten Umsatzdaten abzurufen. Die Funktion verwendet die Azure Event Hubs-Ausgabebindung, um die unstrukturierten Daten als Ereignisse zu senden.

  2. Prozess: Event Hubs löst eine Azure-Funktion aus, die die unstrukturierten Daten verarbeitet und in eine vordefinierte Struktur formatiert. Die Funktion veröffentlicht eine Nachricht an Service Bus pro Ressource, die über die Service Bus-Ausgabebindung importiert werden muss.

  3. Upsert. Service Bus löst eine Azure-Funktion aus, die Nachrichten aus der Warteschlange verwendet und ein Upsert im allgemeinen Unternehmensspeicher ausführt.

Es ist wichtig, potenzielle Vorgangsfehler dieser Architektur zu berücksichtigen. Beispiele hierfür sind:

  • Die interne API ist nicht verfügbar, was zu einer Ausnahme führt, die von der Azure-Datenabfragefunktion im ersten Schritt der Architektur ausgelöst wird.
  • In Schritt 2 ermittelt die Azure-Datenverarbeitungsfunktion Daten, die außerhalb der Bedingungen oder Parameter der Funktion liegen.
  • In Schritt 3 schlägt die Azure-Daten-Upsert-Funktion fehl. Nach mehreren Wiederholungen werden die Nachrichten aus der Warteschlange von Service Bus in die Warteschlange für unzustellbare Nachrichten verschoben. Dabei handelt es sich um eine sekundäre Warteschlange, die Nachrichten enthält, die nach einer vordefinierten Anzahl von Wiederholungen nicht verarbeitet oder nicht an einen Empfänger übermittelt werden können. Danach durchlaufen die Nachrichten einen festgelegten automatischen Prozess oder können manuell verarbeitet werden.

Komponenten

  • Azure Functions ist ein serverloser Dienst, der Ihre Anwendungen verwaltet.
  • Application Insights ist eine Funktion von Azure Monitor, die Anwendungen von der Entwicklung über den Test bis hin zur Produktion überwacht. Application Insights analysiert die Leistung einer Anwendung und überprüft ihre Ausführungsdaten, um die Ursache eines Incidents zu ermitteln.
  • Der Dienst Azure Table Storage speichert nicht relationale strukturierte Daten (strukturierte NoSQL-Daten) in der Cloud und stellt einen Schlüssel-/Attributspeicher mit einem schemalosen Design bereit.
  • Event Hubs ist ein skalierbarer Ereigniserfassungsdienst, der Millionen von Ereignissen pro Sekunde empfangen und verarbeiten kann.
  • OpenCensus umfasst eine Reihe von Open-Source-Bibliotheken, mit denen Sie verteilte Ablaufverfolgungen, Metriken und Telemetriedaten zur Protokollierung sammeln können. Diese Architektur verwendet die Python-Implementierung von OpenCensus.
  • Bei Service Bus handelt es sich um einen vollständig verwalteten Nachrichtenbroker mit Nachrichtenwarteschlangen und Veröffentlichen-Abonnieren-Themen.

Szenariodetails

Verteilte Systeme bestehen aus lose gekoppelten Komponenten. Es kann schwierig sein, zu verstehen, wie die Komponenten kommunizieren und die End-to-End-Journey einer Benutzeranforderung vollständig nachzuvollziehen. Diese Architektur hilft Ihnen zu verstehen, wie Komponenten miteinander verbunden sind.

Wie viele Unternehmen muss Contoso lokale oder Drittanbieterdaten in der Cloud erfassen und gleichzeitig Daten zu ihren Umsätzen mithilfe von Diensten und internen Tools sammeln. In dieser Architektur hat eine Abteilung bei Contoso eine interne API erstellt, die die unstrukturierten Daten verfügbar macht, und erfasst diese Daten in einem allgemeinen Speicher. Der allgemeine Speicher enthält strukturierte Daten aus jeder Abteilung. Die Architektur zeigt, wie Contoso diese Metadaten in der Cloud extrahiert, verarbeitet und erfasst.

Wenn Sie ein System erstellen, insbesondere ein verteiltes System, ist es wichtig, dieses beobachtbar zu machen. Ein beobachtbares System:

  • Bietet einen ganzheitlichen Überblick über die Integrität der verteilten Anwendung.
  • Misst die Betriebsleistung des Systems.
  • Identifiziert und diagnostiziert Fehler, damit Sie ein Problem schnell beheben können.

Verteilte Ablaufverfolgung

In dieser Architektur besteht das System aus einer Kette von Microservices. Jeder Microservice kann aus verschiedenen Gründen unabhängig fehlschlagen. In diesem Fall ist es wichtig zu verstehen, was passiert ist, damit Sie die Problembehandlung durchführen können. Es ist hilfreich, eine End-to-End-Transaktion zu isolieren und die Journey durch den App-Stack zu verfolgen, der aus Diensten oder Microservices besteht. Diese Methode wird als verteilte Ablaufverfolgung bezeichnet.

In den folgenden Abschnitten wird beschrieben, wie die verteilte Ablaufverfolgung in der Architektur eingerichtet wird. Wählen Sie die Schaltfläche In Azure bereitstellen aus, um die Infrastruktur und die Azure-Funktions-App bereitzustellen.

Hinweis

Es gibt keine interne API in der Architektur, sodass das Lesen einer Azure-Datei den Aufruf einer API ersetzt.

In Azure bereitstellen

Ablaufverfolgungen und Spannen

Eine Transaktion wird durch eine Ablaufverfolgung dargestellt, bei der es sich um eine Sammlung von Spannen handelt. Wenn Sie z. B. die Schaltfläche „Kaufen“ auswählen, um eine Bestellung auf einer E-Commerce-Website aufzugeben, finden mehrere nachgelagerte Vorgänge statt. Dazu zählen beispielsweise die folgenden Vorgänge:

  • Eine POST-Anforderung wird an die API übermittelt, die Sie dann auf eine „Warteseite“ weiterleitet.
  • Schreiben von Protokollen mit kontextbezogenen Informationen.
  • Ein externer Aufruf von webbasierter Software, um eine Abrechnungsseite anzufordern.

Jeder dieser Vorgänge kann Teil einer Spanne sein. Die Ablaufverfolgung ist eine vollständige Beschreibung dessen, was passiert, wenn Sie die Schaltfläche „Kaufen“ auswählen.

Wenn die Azure-Datenabfragefunktion die tägliche Erfassung der Umsatzdaten auslöst, wird auf ähnliche Weise in dieser Architektur eine Ablaufverfolgung erstellt, die mehrere Spannen enthält:

  • Eine Spanne zum Bestätigen der Triggerdetails.
  • Eine Spanne zum Abfragen der internen API.
  • Eine Spanne zum Erstellen und Senden eines Ereignisses an Event Hubs.

Eine Spanne kann untergeordnete Spannen enthalten. Die folgende Abbildung zeigt z. B. die Azure-Datenabfragefunktion als Ablaufverfolgung:

Eine Abbildung mit einer vollständigen Ablaufverfolgung, die aus Spannen und deren untergeordneten Spannen besteht.

  • Die sendMessages-Spanne wird in zwei untergeordnete Spannen aufgeteilt: splitToMessages und writeToEventHubs. Die sendMessages-Spanne erfordert diese beiden Untervorgänge, um Nachrichten zu senden.

  • Alle Spannen sind untergeordnete Elemente einer Stammspanne.

  • Spannen bieten Ihnen eine einfache Möglichkeit, alle Teile zu beschreiben, die am Abfrageschritt der Azure-Datenabfragefunktion beteiligt sind. Jede Azure-Funktion ist eine Ablaufverfolgung. Ein End-to-End-Durchlauf durch das Erfassungssystem von Contoso umfasst also die Vereinigung von drei Ablaufverfolgungen, bei denen es sich um die drei Azure-Funktionen handelt. Wenn Sie die drei Ablaufverfolgungen und deren Telemetriedaten kombinieren, erstellen Sie die End-to-End-Journey und beschreiben alle Teile der Architektur.

Tracer und W3C-Ablaufverfolgungskontext

Ein Tracer ist ein Objekt, das kontextbezogene Informationen enthält. Im Idealfall werden diese kontextbezogenen Informationen weitergegeben, wenn die Daten die Azure-Funktionen durchlaufen. Zur Weitergabe der Informationen verwendet die OpenCensus-Erweiterung den W3C-Ablaufverfolgungskontext.

Laut Dokumentation ist der W3C-Ablaufverfolgungskontext eine „Spezifikation, die HTTP-Standardheader und ein Wertformat definiert, um Kontextinformationen zu verteilen, die Szenarien für die verteilte Ablaufverfolgung ermöglichen.“

Eine Komponente des Systems, z. B. eine Funktion, kann einen Tracer mit dem Kontext der vorherigen Komponente erstellen, der den Aufruf durch Lesen der übergeordneten Ablaufverfolgung durchführt. Das Format einer Ablaufverfolgung ist wie folgt:

Traceparent: [version]-[traceId]-[parentId]-[traceFlags]

Zum Beispiel, falls Traceparent = 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-00

base16(version) = 00

base16(traceId) = 0af7651916cd43dd8448eb211c80319c

base16(parentId) = b7ad6b7169203331

base16(traceFlags) = 00

Die Ablaufverfolgungs-ID und die übergeordnete ID sind die wichtigsten Felder. Die Ablaufverfolgungs-ID ist ein global eindeutiger Bezeichner einer Ablaufverfolgung. Die übergeordnete ID ist ein global eindeutiger Bezeichner einer Spanne. Diese Spanne ist Teil der Ablaufverfolgung, die von der Ablaufverfolgungs-ID identifiziert wird.

Weitere Informationen finden Sie unter Traceparent-Header.

In den weiteren Abschnitten dieses Artikels wird davon ausgegangen, dass base16(version) und base16(traceFlags) auf 00 gesetzt sind.

Erstellen einer Ablaufverfolgung mit der OpenCensus-Erweiterung

Verwenden Sie die OpenCensus-Erweiterung, die für Azure Functions spezifisch ist. Verwenden Sie nicht das OpenCensus-Paket, das Sie möglicherweise in anderen Fällen (z. B. Python-Webapps) verwenden würden.

Azure Functions bietet viele Eingabe- und Ausgabebindungen. Jede Bindung bette die übergeordnete Ablaufverfolgung anders ein. Bei dieser Architektur werden bei der Verwendung von Ereignissen und Nachrichten zwei Azure-Funktionen ausgelöst.

Bevor die beiden Funktionen ausgelöst werden können:

  1. Muss der Kontext (gekennzeichnet durch den Bezeichner der Ablaufverfolgung und den Bezeichner der aktuellen Spanne) im Format des W3C-Ablaufverfolgungskontexts in eine übergeordnete Ablaufverfolgung eingebettet werden. Diese Einbettung hängt von der Art der Ausgabebindung ab. So verwendet die Architektur beispielsweise Event Hubs als Messagingsystem. Die übergeordnete Ablaufverfolgung wird in Bytes kodiert und als Diagnose-ID-Eigenschaft in das gesendete Ereignis eingebettet, wodurch der richtige Ablaufverfolgungskontext in der Ausgabebindung erzielt wird.

    Zwei Spannen können verknüpft werden, auch wenn sie nicht übergeordnete und untergeordnete Elemente sind. Bei der verteilten Ablaufverfolgung verweist die aktuelle Spanne auf die nächste. Durch das Erstellen einer Verbindung wird diese Beziehung hergestellt.

    Das Paket Azure Functions Worker verwaltet die Einbettung und Verknüpfung für Sie.

  2. Eine Azure-Funktion in der Mitte des End-to-End-Flows extrahiert die Kontextinformationen aus der übergebenen übergeordneten Ablaufverfolgung. Verwenden Sie die OpenCensus-Erweiterung für Azure Functions für diesen Schritt. Anstatt diesen Prozess im Code jeder Azure-Funktion hinzuzufügen, implementiert die OpenCensus-Erweiterung einen Voraufrufhaken auf Ebene der Funktions-App.

    Der Voraufrufhaken:

    • Erstellt ein span-Kontextobjekt, das die Informationen der vorherigen Spanne enthält und die Azure-Funktion auslöst. Ein visuelles Beispiel für diesen Schritt finden Sie im nächsten Abschnitt.
    • Erstellt einen Tracer, der den span-Kontext enthält, und erstellt eine neue Ablaufverfolgung für die ausgelöste Azure-Funktion.
    • Fügt den Tracer in den Ausführungskontext der Azure-Funktion ein.

    Um sicherzustellen, dass die Ablaufverfolgungen in Application Insights angezeigt werden, müssen Sie die configure-Methode aufrufen, um einen Azure-Exporter zu erstellen und zu konfigurieren, der Telemetriedaten exportiert.

    Die Erweiterung befindet sich auf App-Ebene, sodass die Schritte in diesem Abschnitt für alle Azure-Funktionen in einer Funktions-App gelten.

Verstehen und Strukturieren des Codes

In dieser Architektur ist der Code in den Azure-Funktionen mit Spannen strukturiert. Erstellen Sie in Python eine OpenCensus-Spanne, indem Sie die with-Anweisung verwenden, um auf den span-Kontextteil des Tracer zuzugreifen, der in den Ausführungskontext der Azure-Funktion eingefügt wird. Die folgende Zeichenfolge enthält die Details der aktuellen Spanne und ihrer übergeordneten Elemente:

    with context.tracer.span("nameSpan"):
        # DO SOMETHING WITHIN THAT SPAN

Der folgende Code zeigt Details zur Azure-Datenabfragefunktion:

import datetime
import logging

import azure.functions as func
from opencensus.extension.azure.functions import OpenCensusExtension
from opencensus.trace import config_integration

OpenCensusExtension.configure()
config_integration.trace_integrations(['requests'])
config_integration.trace_integrations(['logging'])

def main(timer: func.TimerRequest, outputEventHubMessage: func.Out[str], context: func.Context) -> None:

    utc_timestamp = datetime.datetime.utcnow().replace(
        tzinfo=datetime.timezone.utc).isoformat()

    if timer.past_due:
        logging.info('The timer is past due!')

    logging.info(f"Query Data Azure Function triggered. Current tracecontext is:      {context.trace_context.Traceparent}")
    with context.tracer.span("queryExternalCatalog"):
        logging.info('querying the external catalog')
        content = {"key_content_1": "thisisavalue1"}
        content = json.dumps(content)

    with context.tracer.span("sendMessage"):
        logging.info('reading the external catalog')

        with context.tracer.span("splitToMessages"):
            # Do sthg
            logging.info('splitting to messages')

        with context.tracer.span("setMessages"): 
            logging.info('sending messages')
            outputEventHubMessage.set(content)

    logging.info('Python timer trigger function ran at %s', utc_timestamp)

Die wichtigsten Punkte in diesem Code sind:

  • Ein OpenCensusExtension.configure-Aufruf. Führen Sie diesen Aufruf nur in einer Azure-Funktion pro Funktions-App aus. Dadurch wird der Azure-Exporter konfiguriert, um Python-Telemetriedaten wie Protokolle, Metriken und Ablaufverfolgungen in Application Insights zu exportieren.

  • OpenCensus requests und logging Integrationen zum Konfigurieren der Erfassung von Telemetriedaten aus den Anforderungs- und Protokollierungsmodulen für HTTP-Aufrufe.

  • Es gibt fünf Spannen:

    • Eine Stammspanne, die Teil des Tracer ist, die vor der Ausführung in den Kontext eingefügt wird
    • queryExternalCatalog
    • sendMessage
    • splitToMessages (ein untergeordnetes Element von sendMessage)
    • setMessages (ein untergeordnetes Element von sendMessage)

Tracer und Spannen

Das folgende Diagramm zeigt, wie der span-Kontext des Tracer jedes Mal aktualisiert wird, wenn eine Spanne erstellt wird.

Eine Abbildung, die die Codezeilen der Funktion zeigt.

Im vorherigen Diagramm:

  1. Eine Azure-Funktion wird ausgelöst. Eine übergeordnete Ablaufverfolgung wird mit einem Voraufrufhaken in das Tracer-Kontextobjekt eingefügt, das vom Python-Worker vor Ausführen der Funktion aufgerufen wird.
  2. Eine Azure-Funktion wird ausgeführt. Die OpenCensusExtension.configure-Methode wird aufgerufen, die einen Azure-Exporter initialisiert und das Schreiben von Ablaufverfolgungen in Application Insights ermöglicht.

Die folgenden Details erläutern die Beziehung zwischen einem Tracer und einer Spanne in dieser Architektur:

  • Das Tracer-Objekt des Azure-Funktionskontexts enthält das Feld span_context, das die Stammspanne beschreibt.
  • Jedes Mal, wenn Sie eine Spanne im Code erstellen, wird ein neuer global eindeutiger Bezeichner erstellt und die span_context-Eigenschaft im Tracer-Objekt des Ausführungskontexts aktualisiert.
  • Das Feld span_context enthält die Felder trace_id und id .
  • Die trace_id wird nie aktualisiert,die id jedoch wird mit dem generierten eindeutigen Bezeichner aktualisiert.
  • Im vorherigen Diagramm hat die Stammspanne zwei untergeordnete Spannen: queryExternalApi und sendMessage.
    • Die Spannen queryExternalApi und sendMessage verfügen über eine neue Spannen-ID, die sich von der root_span_id unterscheidet.
    • Die sendMessage-Spanne hat zwei untergeordnete Spannen: splitToMessages und setMessages. Ihre Spannen-IDs werden im Feld span_context des Tracer-Objekts des Kontexts aktualisiert.
  • Um die Beziehung zwischen einer untergeordneten Spanne und ihrer übergeordneten Spanne zu erfassen, enthält das Feld spans_list die Herkunft der Spannen in Form einer Liste. In der splitToMessages-Spanne enthält das Feld spans_list sendMessage (die übergeordnete Spanne) und splitToMessages (die aktuelle Spanne). Mit dieser Beziehung zwischen übergeordneten und untergeordneten Elementen erstellen Sie die Kette isolierter Vorgänge innerhalb der Ausführung einer Azure-Funktion.

Verketten der Funktionen mithilfe des Kontextfelds

Nachdem die Kette an Vorgängen in einer Azure-Funktion organisiert wurde, können Sie sie mit den nachfolgenden Vorgängen verketten, die von der nächsten Azure-Funktion ausgeführt werden.

Ein Diagramm, das zeigt, wie die Funktionen verkettet werden.

Im vorherigen Diagramm:

  • Die setMessages-Spanne ist die letzte Spanne der Datenabfragefunktion von Azure. Der Code innerhalb der Spanne sendet eine Nachricht an Event Hubs und löst die nachfolgende Azure-Funktion aus. Das Feld span_context des Tracer-Kontextobjekts enthält die Informationen, die sich auf diese Spanne beziehen. Diese Informationen sind an den Kontext der Abfragedaten der Azure-Funktion gebunden.
  • Azure Functions Worker fügt eine bytes-kodierte Diagnose-ID in die Eigenschaften des gesendeten Ereignisses hinzu und erstellt eine Verbindung zur Stammspanne der nachfolgenden Azure-Funktion.
  • Der Voraufrufhaken der nachfolgenden Azure-Datenverarbeitungsfunktion liest die Diagnose-ID und legt den Kontext fest, der die Azure-Funktionen verkettet und die separat ausgeführt werden.

Wenn die Azure-Datenverarbeitungsfunktion eine Nachricht an die Service Bus-Warteschlange sendet, wird der Kontext auf die gleiche Weise übergeben.

Wenn die Überwachungskonfigurationen eingerichtet sind, verwenden Sie die Funktionen von Application Insights, um End-to-End-Transaktionen abzufragen und zu visualisieren.

Telemetrietypen

In Application Insights stehen verschiedene Telemetrietypen zur Verfügung. Der Code in dieser Architektur generiert die folgenden Telemetriedaten:

  • Telemetriedaten zu Anforderungen werden ausgegeben, wenn Sie ein HTTP aufrufen oder eine Azure-Funktion auslösen. Der Eintrag im System von Contoso verfügt über einen Timer zum Auslösen der Azure-Datenabfragefunktion, die Telemetriedaten zu Anforderungen ausgibt.
  • Telemetriedaten zu Abhängigkeiten werden ausgegeben, wenn Sie einen Azure-Dienst oder einen externen Dienst aufrufen. Wenn die Azure-Funktion ein Ereignis in Event Hubs schreibt, gibt sie Telemetriedaten zu Abhängigkeiten aus.
  • Telemetriedaten zur Ablaufverfolgung werden von Protokollen ausgegeben, die von Azure Functions Runtime und Azure Functions generiert wurden. Die Protokollierung in der Azure-Funktion gibt Telemetriedaten zur Ablaufverfolgung aus.

Beitragende

Dieser Artikel wird von Microsoft gepflegt. Er wurde ursprünglich von folgenden Mitwirkenden geschrieben:

Hauptautor:

Andere Mitwirkende:

Melden Sie sich bei LinkedIn an, um nicht öffentliche LinkedIn-Profile anzuzeigen.

Nächste Schritte