Share via


Resilienter Entwurf von Event Hubs und Functions

Fehlerbehandlung, Entwerfen für Idempotenz und Verwaltung des Wiederholungsverhaltens sind einige der kritischen Maßnahmen, die Sie ergreifen können, um sicherzustellen, dass von Event Hubs ausgelöste Funktionen resilient sind und große Datenvolumen verarbeiten können. In diesem Artikel werden diese entscheidenden Konzepte behandelt und Empfehlungen für serverlose Ereignisstreaminglösungen gegeben.

Azure bietet drei Hauptmessagingdienste, die mit Azure Functions verwendet werden können, um eine Vielzahl von einzigartigen, ereignisgesteuerten Szenarien zu unterstützen. Aufgrund des partitionierten Consumermodells und der Fähigkeit, Daten mit einer hohen Rate zu erfassen, wird Azure Event Hubs häufig für Ereignisstreaming- und Big Data-Szenarien verwendet. Einen ausführlichen Vergleich der Azure-Messagingdienste finden Sie unter Auswählen zwischen Azure-Messagingdiensten – Event Grid, Event Hubs und Service Bus.

Vorteile und Herausforderungen von Streaming

Die Kenntnis der Vor- und Nachteile von Streams verhilft zu einem besseren Verständnis, wie ein Dienst wie Event Hubs funktioniert. Sie benötigen diesen Kontext auch, wenn Sie weitreichende Architekturentscheidungen treffen, Probleme behandeln und die Leistung optimieren. Betrachten Sie die folgenden Schlüsselkonzepte von Lösungen, die sowohl Event Hubs als auch Functions verwenden:

  • Streams sind keine Warteschlangen: Event Hubs, Kafka und andere ähnliche Angebote, die auf dem partitionierten Consumermodell aufbauen, unterstützen einige der Hauptfeatures in einem Nachrichtenbroker wie Service Bus nicht intrinsisch. Der vielleicht größte Indikator dafür ist die Tatsache, dass Lesevorgänge nicht destruktiv sind. Dies bedeutet, dass die Daten, die vom Functions-Host gelesen werden, anschließend nicht gelöscht werden. Stattdessen sind Nachrichten unveränderlich und verbleiben, sodass andere Consumer sie auch noch lesen können, einschließlich der Möglichkeit, dass derselbe Kunde sie erneut liest. Aus diesem Grund eignen sich Lösungen, die Muster wie konkurrierende Consumer implementieren, besser für einen herkömmlichen Nachrichtenbroker.

  • Fehlende inhärente Unterstützung für unzustellbare Nachrichten: Ein Kanal für unzustellbare Nachrichten ist kein natives Feature in Event Hubs oder Kafka. Häufig ist das Konzept der Verarbeitung unzustellbarer Nachrichten in eine Streaminglösung integriert, um Daten zu berücksichtigen, die nicht verarbeitet werden können. Diese Funktionalität ist absichtlich kein intrinsisches Element in Event Hubs und wird nur auf Consumerseite hinzugefügt, um ein ähnliches Verhalten oder einen ähnlichen Effekt zu erzielen. Wenn Sie Unterstützung für unzustellbare Nachrichten benötigen, sollten Sie möglicherweise die Wahl Ihres Streamingnachrichtendiensts überprüfen.

  • Eine Arbeitseinheit ist eine Partition: In einem herkömmlichen Nachrichtenbroker ist eine Arbeitseinheit eine einzelne Nachricht. In einer Streaminglösung wird häufig eine Partition als Arbeitseinheit betrachtet. Wenn jedes Ereignis in einem Event Hub als diskrete Nachricht betrachtet wird, die es erforderlich macht, dass sie wie ein Auftragsverarbeitungsvorgang oder eine Finanztransaktion behandelt wird, ist dies höchstwahrscheinlich ein Hinweis darauf, dass der falsche Messagingdienst verwendet wird.

  • Keine serverseitige Filterung: Einer der Gründe, warum Event Hubs eine enorme Skalierung und einen hohen Durchsatz erzielen kann, ist der geringe Mehraufwand, der mit dem Dienst selbst einhergeht. Features wie serverseitige Filterung, Indizes und brokerübergreifende Koordination sind nicht Teil der Architektur von Event Hubs. Funktionen werden gelegentlich verwendet, um Ereignisse zu filtern, indem sie an andere Event Hubs basierend auf dem Inhalt im Text oder Header weitergeleitet werden. Dieser Ansatz ist beim Ereignisstreaming üblich, hat jedoch den Nachteil, dass jedes Ereignis von der ursprünglichen Funktion gelesen und ausgewertet wird.

  • Jeder Leser muss alle Daten lesen: Da die serverseitige Filterung nicht verfügbar ist, liest ein Consumer sequenziell alle Daten in einer Partition. Dies schließt Daten ein, die möglicherweise nicht relevant sind oder sogar falsch formatiert sein können. Es gibt mehrere Optionen und sogar Strategien, die zur Kompensation dieser Herausforderungen verwendet werden können, die später in diesem Abschnitt behandelt werden.

Diese signifikanten Entwurfsentscheidungen ermöglichen es Event Hubs, das zu tun, was es am besten kann: einen erheblichen Zustrom von Ereignissen unterstützen und einen robusten und resilienten Dienst zu bieten, aus dem Consumer lesen können. Jede Consumeranwendung ist dafür verantwortlich, ihre eigenen clientseitigen Offsets oder Cursor für diese Ereignisse zu verwalten. Der geringe Mehraufwand macht Event Hubs zu einer kostengünstigen und leistungsstarken Option für das Ereignisstreaming.

Idempotenz

Einer der wichtigsten Grundsätze von Azure Event Hubs ist das Konzept der „mindestens einmaligen Zustellung“. Dieser Ansatz stellt sicher, dass Ereignisse immer übermittelt werden. Dies bedeutet auch, dass Ereignisse mehrmals, sogar wiederholt, von Consumern wie einer Funktion empfangen werden können. Aus diesem Grund ist es wichtig, dass eine von einem Event Hub ausgelöste Funktion das Muster idempotenter Consumer unterstützt.

Das Arbeiten unter der Voraussetzung einer mindestens einmaligen Zustellung, insbesondere im Kontext einer ereignisgesteuerten Architektur, ist ein verantwortungsvoller Ansatz für die zuverlässige Verarbeitung von Ereignissen. Ihre Funktion muss idempotent sein, damit das Ergebnis der mehrfachen Verarbeitung desselben Ereignisses mit dessen einmaliger Verarbeitung identisch ist.

Doppelte Ereignisse

Es gibt mehrere unterschiedliche Szenarien, die dazu führen können, dass doppelte Ereignisse an eine Funktion übergeben werden:

  • Setzen von Prüfpunkten: Wenn der Azure Functions-Host abstürzt oder der für die Häufigkeit von Batchprüfpunkten festgelegte Schwellenwert nicht erreicht wird, wird kein Prüfpunkt erstellt. Daher wird der Offset für den Consumer nicht fortgeschrieben, und wenn die Funktion das nächste Mal aufgerufen wird, wird sie ab dem letzten Prüfpunkt fortgesetzt. Es ist wichtig zu beachten, dass das Setzen von Prüfpunkten für jeden Consumer auf Partitionsebene erfolgt.

  • Veröffentlichung doppelter Ereignisse: Es gibt viele Methoden, die die Möglichkeit der Veröffentlichung desselben Ereignisses in einem Stream mindern könnten. Es liegt jedoch weiterhin in der Verantwortung des Consumers, Duplikate idempotent zu verarbeiten.

  • Fehlende Bestätigungen: In einigen Situationen kann eine ausgehende Anforderung an einen Dienst erfolgreich sein, doch eine Bestätigung (ACK) vom Dienst wird nie empfangen. Dies kann zu der Wahrnehmung führen, dass der ausgehende Aufruf fehlgeschlagen ist, und eine Reihe von Wiederholungsversuchen oder andere Ergebnisse aus der Funktion auslösen. Am Ende können doppelte Ereignisse veröffentlicht werden, oder ein Prüfpunkt wird nicht erstellt.

Deduplizierungsmethoden

Das Entwerfen Ihrer Funktionen für identische Eingaben sollte der Standardansatz sein, wenn er mit der Event Hub-Triggerbindung gekoppelt wird. Sie sollten die folgenden Methoden erwägen:

  • Suchen nach Duplikaten: Ergreifen Sie vor der Verarbeitung die erforderlichen Maßnahmen, um zu überprüfen, ob das Ereignis verarbeitet werden sollte. In einigen Fällen macht dies eine Untersuchung erforderlich, um zu bestätigen, dass es noch gültig ist. Es kann auch sein, dass die Behandlung des Ereignisses aufgrund der Aktualität der Daten oder der Logik, die das Ereignis ungültig macht, nicht mehr erforderlich ist.

  • Entwerfen von Ereignissen für Idempotenz: Durch die Bereitstellung zusätzlicher Informationen innerhalb der Nutzdaten des Ereignisses kann eventuell sichergestellt werden, dass seine mehrfache Verarbeitung keine negativen Auswirkungen hat. Nehmen wir das Beispiel eines Ereignisses, das einen Betrag zur Abhebung von einem Bankkonto enthält. Wenn dieses nicht verantwortungsbewusst gehandhabt wird, könnte es dazu kommen, dass der Betrag mehrfach vom Konto abgebucht wird. Wenn dasselbe Ereignis jedoch den aktualisierten Saldo für das Konto enthält, könnte dies verwendet werden, um einen Upsertvorgang für den Kontostand des Bankkontos durchzuführen. Dieser ereignisgestützte Ansatz zur Zustandsübertragung erfordert gelegentlich die Koordination zwischen Producern und Consumern und sollte verwendet werden, wenn er für beteiligte Dienste sinnvoll ist.

Fehlerbehandlung und Wiederholungsversuche

Fehlerbehandlung und Wiederholungsversuche sind einige der wichtigsten Eigenschaften verteilter, ereignisgesteuerter Anwendungen, wobei Functions keine Ausnahme darstellt. Bei Ereignisstreaminglösungen ist eine ordnungsgemäße Unterstützung der Fehlerbehandlung von entscheidender Bedeutung, da Tausende von Ereignissen schnell zu einer gleichen Anzahl von Fehlern werden können, wenn sie nicht ordnungsgemäß behandelt werden.

Anleitung zur Fehlerbehandlung

Ohne Fehlerbehandlung kann es schwierig sein, Wiederholungsversuche zu implementieren, Laufzeitausnahmen zu erkennen und Probleme zu untersuchen. Jede Funktion sollte mindestens ein gewisses Niveau an Fehlerbehandlung aufweisen. Einige empfohlene Richtlinien sind:

  • Verwenden von Application Insights: Aktivieren und verwenden Sie Application Insights, um Fehler zu protokollieren und die Integrität Ihrer Funktionen zu überwachen. Beachten Sie die konfigurierbaren Stichprobenentnahmeoptionen für Szenarien, die ein großes Volumen von Ereignissen verarbeiten.

  • Hinzufügen strukturierter Fehlerbehandlung: Wenden Sie die geeigneten Fehlerbehandlungskonstrukte für die jeweilige Programmiersprache an, um erwartete und nicht behandelte Ausnahmen in Ihrem Funktionscode abzufangen, zu protokollieren und zu erkennen. Verwenden Sie beispielsweise einen try/catch-Block in C#, Java und JavaScript, und nutzen Sie die try- und except-Blöcke in Python, um Ausnahmen zu behandeln.

  • Protokollierung: Das Abfangen einer Ausnahme während der Ausführung bietet eine Möglichkeit, kritische Informationen zu protokollieren, die verwendet werden können, um Probleme zuverlässig zu erkennen, zu reproduzieren und zu beheben. Protokollieren Sie die Ausnahme, nicht nur die Meldung, sondern auch den Text, die innere Ausnahme und andere nützliche Artefakte, die später hilfreich sein werden.

  • Ausnahmen nicht abfangen und ignorieren: Das Schlechteste, was Sie machen können, ist, eine Ausnahme abzufangen und nichts damit zu machen. Wenn Sie eine generische Ausnahme abfangen, protokollieren Sie sie an einem Ort. Wenn Sie Fehler nicht protokollieren, ist es schwierig, Fehler und gemeldete Probleme zu untersuchen.

Wiederholungsversuche

Das Implementieren einer Wiederholungslogik in eine Ereignisstreamingarchitektur kann komplex sein. Die Unterstützung von Abbruchtoken, Wiederholungszählern und exponentiellen Backoff-Strategien sind nur einige der Aspekte, die es schwierig machen. Glücklicherweise bietet Functions Wiederholungsrichtlinien, die viele dieser Aufgaben erfüllen können, die Sie normalerweise selbst programmieren würden.

Wichtige Faktoren, die bei der Verwendung der Wiederholungsrichtlinien mit der Event Hub-Bindung berücksichtigt werden müssen, sind unter anderem:

  • Vermeiden unbegrenzter Wiederholungsversuche: Wenn die Einstellung max retry count (max. Anzahl Wiederholungsversuche) auf den Wert „-1“ festgelegt ist, wird die Funktion unbegrenzt wiederholt. Im Allgemeinen sollten unbegrenzte Wiederholungsversuche nur sehr sparsam mit Functions und praktisch nie mit der Event Hub-Triggerbindung verwendet werden.

  • Auswählen der geeigneten Wiederholungsstrategie: Eine feste Verzögerungsstrategie kann für Szenarien optimal sein, in denen es zu Rückstau von anderen Azure-Diensten kommt. In diesen Fällen kann die Verzögerung dazu beitragen, eine Drosselung und andere Einschränkungen durch diese Dienste zu vermeiden. Die exponentielle Backoff-Strategie bietet mehr Flexibilität für Verzögerungsintervalle von Wiederholungsversuchen und wird häufig bei der Integration in Drittanbieterdienste, REST-Endpunkte und andere Azure-Dienste verwendet.

  • Intervalle und Anzahl von Wiederholungsversuchen niedrig halten: Versuchen Sie nach Möglichkeit, ein Wiederholungsintervall beizubehalten, das kürzer als eine Minute ist. Halten Sie außerdem die maximale Anzahl von Wiederholungsversuchen auf einer einigermaßen niedrigen Anzahl. Diese Einstellungen sind besonders relevant, wenn sie im Functions-Verbrauchsplan ausgeführt werden.

  • Trennschaltermuster (Circuit Breaker) : Ein vorübergehender Fehler wird von Zeit zu Zeit erwartet und stellt einen natürlichen Anwendungsfall für Wiederholungsversuche dar. Wenn jedoch während der Verarbeitung der Funktion eine erhebliche Anzahl von Fehlern oder Problemen auftritt, kann es sinnvoll sein, die Funktion zu beenden, die Probleme zu beheben und später neu zu starten.

Eine wichtige Schlussfolgerung für die Wiederholungsrichtlinien in Functions ist, dass es sich um ein „Best Effort“-Feature für die erneute Verarbeitung von Ereignissen handelt. Dies ersetzt nicht die Notwendigkeit für eine Fehlerbehandlung, für Protokollierung und andere wichtige Muster, die Resilienz für Ihren Code bereitstellen.

Strategien für Fehler und beschädigte Daten

Es gibt mehrere beachtenswerte Ansätze, die Sie verwenden können, um Probleme zu kompensieren, die aufgrund von Fehlern oder ungültigen Daten in einem Ereignisstream auftreten. Einige grundlegende Strategien sind:

  • Senden und Lesen beenden: Halten Sie das Lesen und Schreiben von Ereignissen an, um das zugrunde liegende Problem zu beheben. Der Vorteil dieses Ansatzes ist, dass Daten nicht verloren gehen und Vorgänge fortgesetzt werden können, nachdem eine Korrektur durchgeführt wurde. Dieser Ansatz erfordert möglicherweise eine Trennschalterkomponente in der Architektur und möglicherweise eine Benachrichtigung an die betroffenen Dienste, um eine Pause zu erreichen. In manchen Fällen kann es erforderlich sein, eine Funktion zu beenden, bis die Probleme behoben sind.

  • Nachrichten verwerfen: Wenn Nachrichten nicht wichtig sind oder als nicht unternehmenskritisch betrachtet werden, sollten Sie erwägen fortzufahren, ohne sie zu verarbeiten. Dies funktioniert nicht in Szenarien, die starke Konsistenz erfordern, z. B. das Aufzeichnen von Zügen in einem Schachspiel oder Finanztransaktionen. Die Fehlerbehandlung innerhalb einer Funktion wird zum Abfangen und Verwerfen von Nachrichten empfohlen, die nicht verarbeitet werden können.

  • Wiederholen: Es gibt viele Situationen, die die erneute Verarbeitung eines Ereignisses rechtfertigen können. Das häufigste Szenario ist ein vorübergehender Fehler, der beim Aufrufen eines anderen Diensts oder einer Abhängigkeit auftritt. Netzwerkfehler, Diensteinschränkungen und -verfügbarkeit sowie starke Konsistenz sind möglicherweise die häufigsten Anwendungsfälle, die erneute Verarbeitungsversuche rechtfertigen.

  • Unzustellbare Nachricht: Die Idee hierbei besteht darin, das Ereignis in einem anderen Event Hub zu veröffentlichen, damit der bestehende Flow nicht unterbrochen wird. Die Wahrnehmung ist, dass sie aus dem heißen Pfad verschoben wurde und später oder von einen anderen Prozess verarbeitet werden könnte. Diese Lösung wird häufig für die Behandlung nicht verarbeiteter Nachrichten oder Ereignisse verwendet. Beachten Sie, dass jede Funktion, die mit einer anderen Consumergruppe konfiguriert ist, weiterhin auf die ungültigen oder beschädigten Daten in ihrem Datenstrom trifft und verantwortungsbewusst damit umgehen muss.

  • Wiederholung und unzustellbare Nachricht: Die Kombination aus zahlreichen Wiederholungsversuchen vor der endgültigen Veröffentlichung in einem Stream für unzustellbare Nachrichten, sobald ein Schwellenwert erreicht wurde, ist eine weitere gängige Methode.

  • Verwenden einer Schemaregistrierung: Eine Schemaregistrierung kann als proaktives Tool verwendet werden, um bei der Verbesserung der Konsistenz und Datenqualität zu helfen. Die Azure-Schemaregistrierung kann den Übergang von Schemas zusammen mit der Versionsverwaltung und verschiedenen Kompatibilitätsmodi unterstützen, wenn sich Schemas weiterentwickeln. Im Kern fungiert das Schema als Vertrag zwischen Producern und Consumern, wodurch die Möglichkeit verringert werden kann, dass ungültige oder beschädigte Daten im Stream veröffentlicht werden.

Letztendlich gibt es keine perfekte Lösung, und die Folgen und Kompromisse jeder der Strategien müssen gründlich untersucht werden. Basierend auf den Anforderungen kann die gemeinsame Verwendung mehrerer dieser Methoden der beste Ansatz sein.

Beitragende

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

Hauptautor:

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

Nächste Schritte

Bevor Sie fortfahren, sollten Sie die folgenden verwandten Artikel lesen: