Skalieren Ihrer Verarbeitungsanwendung

Abgeschlossen

Um die Ereignisverarbeitungsanwendung zu skalieren, können Sie mehrere Instanzen der Anwendung ausführen und die Auslastung zwischen diesen untereinander ausgleichen. In älteren Versionen konnte EventProcessorHost die Last zwischen mehreren Instanzen Ihres Programms und Prüfpunktereignissen bei deren Empfang ausgleichen. In den neueren Versionen (5.0 oder höher) ermöglichen EventProcessorClient (.NET und Java) oder EventHubConsumerClient (Python und JavaScript) die gleiche Funktionalität.

Hinweis

Der Schlüssel zur Skalierung in Event Hubs ist das Konzept der partitionierten Consumer. Im Gegensatz zum Muster der konkurrierenden Consumer ermöglicht das Muster der partitionierten Consumer hohe Skalierbarkeit durch Beseitigen des Konfliktengpasses und Vereinfachen der End-to-End-Parallelität.

Beispielszenario

Als Beispielszenario soll ein Unternehmen für Alarmsysteme dienen, das 100.000 Häuser überwacht. Jede Minute gehen Daten von verschiedenen Sensoren im Unternehmen ein, z. B. von Bewegungsmeldern, Tür- und Fensteröffnungsmeldern oder Glasbruchsensoren, die in jedem Haus montiert sind. Das Unternehmen stellt für Kunden eine Website zum Überwachen der Aktivitäten im Haus nahezu in Echtzeit bereit.

Jeder Melder überträgt Daten an einen Event Hub. Der Event Hub ist mit 16 Partitionen konfiguriert. Auf der Nutzungsseite benötigen Sie einen Mechanismus, der diese Ereignisse lesen, konsolidieren und das Aggregat in einem Speicherblob speichern kann, das dann auf eine benutzerfreundliche Webseite projiziert wird.

Beim Entwerfen des Consumers in einer verteilten Umgebung muss das Szenario die folgenden Anforderungen erfüllen:

  • Skalierung: Erstellen mehrerer Consumer, wobei jeder Consumer die Besitzrechte für das Lesen einiger Event Hubs-Partitionen übernimmt.
  • Lastenausgleich: Dynamisches Erhöhen oder Verringern der Consumer. Wenn beispielsweise in jedem Haus ein neuer Melder (z.B. ein Kohlenmonoxidmelder) montiert wird, erhöht sich die Anzahl der Ereignisse. In diesem Fall erhöht der (menschliche) Bediener die Anzahl der Consumerinstanzen. Anschließend kann der Pool von Consumern die Anzahl der Partitionen in ihrem Besitz neu ausgleichen, um die Last auch auf die neu hinzugefügten Consumer zu verteilen.
  • Nahtloses Fortsetzen nach Fehlern: Wenn bei einem Consumer (Consumer A) ein Fehler auftritt (der virtuelle Computer, der den Consumer hostet, stürzt z.B. plötzlich ab), müssen andere Consumer die Partitionen im Besitz von Consumer A aufnehmen und fortfahren können. Außerdem muss der Fortsetzungspunkt, der als Prüfpunkt oder Offset bezeichnet wird, genau an dem Punkt oder etwas früher liegen, an dem der Fehler bei Consumer A aufgetreten ist.
  • Nutzen von Ereignissen: Während die drei vorherigen Punkte die Verwaltung des Consumers betreffen, ist außerdem Code zum Nutzen und sinnvollen Verarbeiten der Ereignisse erforderlich. Beispielsweise zum Aggregieren und Hochladen in Blobspeicher.

Ereignisprozessor oder Consumerclient

Sie müssen keine eigene Lösung erstellen, um diese Anforderungen zu erfüllen. Diese Funktionalität wird von den Azure-Event Hubs SDKs bereitgestellt. In .NET oder Java SDKs verwenden Sie einen Ereignisprozessorclient (EventProcessorClient), und in Python und JavaScript SDKs verwenden Sie EventHubConsumerClient.

Für die meisten Produktionsszenarien wird empfohlen, den Ereignisprozessorclient zum Lesen und Verarbeiten von Ereignissen zu verwenden. Ereignisprozessorclients können auch im Kontext einer Consumergruppe für einen bestimmten Event Hub zusammenarbeiten. Verteilung und Lastenausgleich werden von Clients automatisch verwaltet, wenn Instanzen für die Gruppe verfügbar werden oder nicht verfügbar sind.

Nachverfolgen des Partitionsbesitzes

Eine Ereignisprozessorinstanz ist in der Regel Besitzer von Ereignissen und verarbeitet Ereignisse aus mindestens einer Partition. Der Besitz von Partitionen wird gleichmäßig auf alle aktiven Ereignisprozessorinstanzen verteilt, die mit einer Kombination aus Event Hub und Consumergruppe verknüpft sind.

Jeder Ereignisprozessor erhält einen eindeutigen Bezeichner und beansprucht den Besitz von Partitionen, indem ein Eintrag in einem Prüfpunktspeicher hinzugefügt oder aktualisiert wird. Alle Ereignisprozessorinstanzen kommunizieren in regelmäßigen Abständen mit diesem Speicher, um den eigenen Verarbeitungsstatus zu aktualisieren und Informationen zu anderen aktiven Instanzen zu erhalten. Diese Daten werden dann verwendet, um die Last zwischen den aktiven Prozessoren auszugleichen.

Empfangen von Nachrichten

Wenn Sie einen Ereignisprozessor erstellen, geben Sie die Funktionen an, mit denen Ereignisse und Fehler verarbeitet werden. Jeder Aufruf der Funktion, die Ereignisse verarbeitet, liefert ein einzelnes Ereignis aus einer bestimmten Partition. Die Verarbeitung dieses Ereignisses liegt in Ihrer Verantwortung. Wenn Sie sicherstellen möchten, dass der Consumer jede Nachricht mindestens ein Mal verarbeitet, müssen Sie Ihren eigenen Code mit Wiederholungslogik schreiben. Lassen Sie bei nicht verarbeitbaren Nachrichten jedoch Vorsicht walten.

Es wird empfohlen, relativ schnell vorzugehen. Das heißt: Führen Sie so wenig Verarbeitung wie möglich durch. Wenn Ereignisse in den Speicher geschrieben und Routingvorgänge durchgeführt werden müssen, empfiehlt es sich, zwei Consumergruppen zu verwenden und zwei Ereignisprozessoren einzusetzen.

Setzen von Prüfpunkten

Das Festlegen von Prüfpunkten ist ein Vorgang, durch den ein Ereignisprozessor die Position des letzten erfolgreich verarbeiteten Ereignisses innerhalb einer Partition markiert oder committet. Das Markieren eines Prüfpunkts erfolgt in der Regel innerhalb der Funktion, die die Ereignisse verarbeitet, und wird pro Partition innerhalb einer Consumergruppe ausgeführt.

Wenn ein Ereignisprozessor die Verbindung mit einer Partition trennt, kann eine andere Instanz die Verarbeitung der Partition am Prüfpunkt fortsetzen, für den zuvor vom letzten Prozessor dieser Partition in dieser Consumergruppe ein Commit ausgeführt wurde. Wenn der Prozessor eine Verbindung herstellt, übergibt er den Offset an den Event Hub, um die Position für den Beginn des nächsten Lesevorgangs anzugeben. Auf diese Weise können mithilfe von Prüfpunkten Ereignisse von Downstreamanwendungen als abgeschlossen markiert werden. Darüber hinaus sorgen Prüfpunkte für Resilienz, wenn ein Ereignisprozessor ausfällt. Sie können ältere Daten zurückgeben, indem Sie einen niedrigeren Offset aus diesem Prüfpunktprozess angeben.

Threadsicherheit und Prozessorinstanzen

Standardmäßig wird die Funktion zur Verarbeitung der Ereignisse für eine bestimmte Partition sequenziell aufgerufen. Nachfolgende Ereignisse und Aufrufe dieser Funktion über eine Partition sammeln sich im Hintergrund in der Warteschlange an, da das Ereignissystem weiterhin im Hintergrund in anderen Threads ausgeführt wird. Ereignisse unterschiedlicher Partitionen können gleichzeitig verarbeitet werden. Freigegebene Status, auf die über Partitionen hinweg zugegriffen wird, müssen synchronisiert werden.