Verarbeiten Sie eine Reihe verwandter Nachrichten in einer festgelegten Reihenfolge, ohne die Verarbeitung anderer Nachrichtengruppen zu blockieren.
Kontext und Problem
Anwendungen müssen häufig eine Reihe von Nachrichten in der Reihenfolge verarbeiten, in der sie empfangen werden, und gleichzeitig horizontal hochskalieren, um die erhöhte Auslastung zu verarbeiten. In einer verteilten Architektur ist die Verarbeitung dieser Nachrichten in der richtigen Reihenfolge nicht ganz einfach, da die Worker unabhängig voneinander skalieren können und die Nachrichten oft unabhängig mithilfe von Pull übertragen werden, indem sie das Muster „Konkurrierende Consumer“ verwenden.
Ein System zur Auftragsnachverfolgung erhält z. B. einen Ledger, der Aufträge und die relevanten Vorgänge für diese Aufträge enthält. Mit diesen Vorgängen kann ein Auftrag erstellt, dem Auftrag eine Transaktion hinzugefügt, eine vergangene Transaktion geändert oder ein Auftrag gelöscht werden. In diesem System müssen Vorgänge nach dem FIFO-Prinzip (First In, First Out) ausgeführt werden, allerdings nur auf Auftragsebene. Die anfängliche Warteschlange erhält jedoch einen Ledger, der Transaktionen für viele Aufträge enthält, die möglicherweise verschachtelt sind.
Lösung
Übertragen Sie verwandte Nachrichten in Kategorien innerhalb des Warteschlangensystems mithilfe von Push, und lassen Sie die Warteschlangenlistener nur für eine Kategorie für jeweils eine Nachricht Sperr- und Pullvorgänge ausführen.
Das allgemeine Muster für den sequenziellen Konvoi sieht wie folgt aus:
In der Warteschlange können Nachrichten für verschiedene Kategorien verschachtelt sein, wie im folgenden Diagramm dargestellt:
Probleme und Überlegungen
Beachten Sie die folgenden Punkte bei der Entscheidung, wie dieses Muster implementiert werden soll:
- Kategorie/Skalierungseinheit: Für welche Eigenschaft der eingehenden Nachrichten können Sie horizontal hochskalieren? Im Szenario zur Auftragsnachverfolgung ist diese Eigenschaft die Auftrags-ID.
- Durchsatz. Wie ist der Durchsatz Ihrer Zielnachricht? Wenn er sehr hoch ist, müssen Sie möglicherweise Ihre FIFO-Anforderungen überdenken. Können Sie z. B. eine Start- oder Endnachricht erzwingen, nach der Zeit sortieren und dann einen Batch für die Verarbeitung senden?
- Gerätefunktionen: Ermöglicht die Auswahl des Nachrichtenbus die einmalige Verarbeitung von Nachrichten in einer Warteschlange oder einer Kategorie einer Warteschlange?
- Evolvierbarkeit: Wie wird dem System eine neue Nachrichtenkategorie hinzugefügt? Nehmen wir beispielsweise an, dass das oben beschriebene Ledgersystem spezifisch für einen Kunden ist. Wenn Sie für einen neuen Kunden ein Onboarding durchführen müssen, können Sie über mehrere Ledgerprozessoren verfügen, die Arbeit pro Kunden-ID verteilen?
- Es ist möglich, dass Consumer aufgrund variabler Netzwerklatenz beim Senden von Nachrichten eine Nachricht möglicherweise nicht in der richtigen Reihenfolge erhalten. Verwenden Sie zum Überprüfen der Reihenfolge die Sequenznummern. Sie können auch ein spezielles Flag „Ende der Sequenz“ in die letzte Nachricht der Transaktion einschließen. Technologien zur Streamverarbeitung wie Spark oder Azure Stream Analytics können Nachrichten innerhalb eines Zeitfensters in der richtigen Reihenfolge verarbeiten.
Verwendung dieses Musters
Verwenden Sie dieses Muster in folgenden Fällen:
- Sie haben Nachrichten, die in der richtigen Reihenfolge eintreffen und in derselben Reihenfolge verarbeitet werden müssen.
- Eingehende Nachrichten können so „kategorisiert“ werden, dass die Kategorie zu einer Skalierungseinheit für das System wird.
Dieses Muster ist in folgendem Fall möglicherweise nicht geeignet:
- Extrem hohe Durchsatzszenarios (Millionen von Nachrichten pro Minute oder Sekunde), da die FIFO-Anforderung die Skalierung einschränkt, die vom System durchgeführt werden kann.
Workloadentwurf
Ein Architekt sollte evaluieren, wie das Sequential Convoy-Pattern im Design seiner Workloads verwendet werden kann, um die Ziele und Prinzipien zu erreichen, die in den Säulen des Azure Well-Architected Framework behandelt werden. Zum Beispiel:
Säule | So unterstützt dieses Muster die Säulenziele |
---|---|
Zuverlässigkeitsdesignentscheidungen tragen dazu bei, dass Ihre Workload ausfallsicher wird und dass sie nach einem Ausfall wieder in einen voll funktionsfähigen Zustand zurückkehrt. | Mit diesem Muster können schwer zu behebende Wettlaufbedingungen, umstrittene Nachrichtenbehandlung oder andere Umgehungslösungen für die Adressierung falsch geordneter Nachrichten, die zu Fehlfunktionen führen können, vermieden werden. - RE:02 Kritische Flows - RE:07 Hintergrundaufträge |
Berücksichtigen Sie wie bei jeder Designentscheidung alle Kompromisse im Hinblick auf die Ziele der anderen Säulen, die mit diesem Muster eingeführt werden könnten.
Beispiel
In Azure kann dieses Muster mithilfe von Nachrichtensitzungen von Azure Service Bus implementiert werden. Für die Consumer können Sie entweder Logik-Apps mit dem Service Bus-Peek-Lock-Connector oder Azure Functions mit dem Service Bus-Trigger verwenden.
Verarbeiten Sie im vorherigen Beispiel zur Auftragsnachverfolgung jede Ledgernachricht in der Reihenfolge, in der sie empfangen wird, und senden Sie jede Transaktion an eine andere Warteschlange, in der die Kategorie auf die Auftrags-ID festgelegt ist. Eine Transaktion umfasst in diesem Szenario nie mehrere Aufträge, sodass die Kunden jede Kategorie parallel, aber FIFO innerhalb der Kategorie verarbeiten.
Der Ledgeprozessor gibt alle Nachrichten aus, indem der Inhalt der einzelnen Nachrichten in der ersten Warteschlange aufgeschlüsselt wird:
Der Ledgerprozessor kümmert sich um Folgendes:
- Der Ledger durchläuft eine Transaktion nach der anderen.
- Die Sitzungs-ID der Nachricht wird entsprechend der Auftrags-ID festgelegt.
- Jede Ledgertransaktion wird an eine sekundäre Warteschlange gesendet, wobei die Sitzungs-ID auf die Auftrags-ID festgelegt ist.
Die Consumer lauschen an der sekundären Warteschlange, in der alle Nachrichten mit übereinstimmenden Auftrags-IDs in Reihenfolge aus der Warteschlange verarbeitet werden. Die Consumer verwenden den Peek-Lock-Modus.
Wenn Sie die Skalierbarkeit berücksichtigen, stellt die Ledgerwarteschlange einen primären Engpass dar. Verschiedene Transaktionen, die für den Ledger bereitgestellt werden, können auf die gleiche Auftrags-ID verweisen. Nachrichten können jedoch nach dem Ledger an die Anzahl der Aufträge in einer serverlosen Umgebung gesendet werden.
Nächste Schritte
Die folgenden Informationen sind unter Umständen auch relevant, wenn dieses Muster implementiert wird: