Redelivery beim ActiveMQ und anderen JMS Message Brokern

Mach’s noch einmal, Sam

Warum Redelivery?

Die erneute Zustellung von Nachrichten im Fehlerfall ist ein mächtiges Pattern für verteilte, robuste und skalierbare Systeme.

Das Fehlerhandling ist bei der Entwicklung aufwendig und kann mehr Zeit kosten, als die eigentliche Entwicklung. Der Redelivery Mechanismus und das Dead Letter Queue Pattern, helfen ein zuverlässiges Fehlerhandling mit wenig Aufwand zu realisieren. Message Broker wie der Apache ActiveMQ oder der RabbitMQ kommen mit Redelivery out of the Box. Wie die Redeliveries genau ablaufen, wann, wie oft und in welcher Reihenfolge kann angepasst werden. Das für eine Anpassung notwendig grundlegende Verständis für Redeliveries wird in diesem Artikel vermittelt.

Erfolgreiche Zustellung

Bevor wir Redeliveries betrachten, beschäftigen wir uns zuerst mit dem Fall einer folgreichen Zustellung.

working-example

Abbildung 1: Fehlerfreie Zustellung und Verarbeitung einer Nachricht

Senden

Eine Nachricht wird in Schritt 1 (Abbildung 1) durch den Producer an eine Queue gesendet. In einer Queue können mehrere Nachrichten liegen, welche sequentiell nach dem FiFo (first in first out) Prinzip abgearbeitet werden.

Auslesen

In Schritt 2 (Abbildung1) wird die erste Nachricht aus der Queue an den Consumer weiteregeleitet.

Acknowledge

Die Nachricht befindet sich so lange in der Queue, bis der Consumer der Queue mitteilt, dass die Nachricht erfolgreich verarbeitet wurde. Im Beispiel besteht die Verarbeitung aus der Ablage der Nachricht in einer Datenbank. Dies geschieht in Schritt 3 (Abbildung 1). Nach erfolgreicher Verarbeitung sendet der Consumer eine Bestätigung, das Ackownledge (ACK) an den Broker. Die Nachricht wird anschließend durch den Broker aus der Queue entfernt.

Fehlerhafte Verarbeitung

Anders als in Abbildung 1 tritt in diesem Szenario ein Fehler bei der Weiterverarbeitung der Nachricht durch den Consumer auf. Ursache ist eine gestörte Verbindung zur Datenbank(3). Der Consumer sendet deshalb ein Not Acknowledge(NACK) Signal an die Queue(4). Als Resultat, wird ein erneuter Zustellungsversuch der Nachricht unternommen. Wie oft, und in welchen Zeitabständen Versuche erfolgen ist von der Konfiguration des MessageBrokers oder der Verbindung abhängig.

broken-sample

Abbildung 2: Fehlerhafte Nachrichtenverarbeitung

Ist die wiederholte Zustellung nicht erfolgreich, wird die Nachricht an eine DeadLetterQueue(DLQ) weitergeleitet, um das System nicht weiter zu blockieren ohne die Message zu verlieren.

Was führt zum Redelivery

Ein Fehler während der Verarbeitung einer Nachricht kann zu einem Redelivery führen, falls der Consumer durch ein NACK dem Broker signalisiert, dass es zu einem Fehler gekommen ist.

Wird weder ein ACK noch ein NACK an den Broker gesendet, so kommt es zu einem Timeout. In diesem Fall entscheidet der Broker selbst, dass es zu einem Fehler gekommen sein muss und es erfolgt eine erneute Zustellung der Nachricht.

Ursachen

„Die reinste Form des Wahnsinns ist es, alles beim Alten zu lassen und gleichzeitig zu hoffen, dass sich etwas ändert.“ – Albert Einstein[1]

Dem Zitat zu Folge könnte man denken, dass ein erneuter Zustellversuch wenig Sinn macht, doch trifft dies hier nur bedingt zu. An dieser Stelle muss zwischen 2 Gruppen von Ursachen unterschieden werden.

Es könnte sich beispielsweise um ein temporäres technisches Problem des Consumers handeln, z.B. wenn vom Client genutzte Ressourcen nicht verfügbar sind.

Technische Ursache

Technische Ursache während des Versands und der Verarbeitung einer Nachricht könnten die folgenden sein:

  • Die Festplatte ist voll
  • Netzwerkverbindungen sind unterbrochen
  • Wartungen an Teilen des Systems werden durchgeführt
  • Die Datenbank ist nicht verfügbar
  • Das Zielsystem steht in Flammen
  • ...
Bei diesen Ursachen machen erneute Zustellversuche Sinn, es besteht die Möglichkeit dass das System wieder verbunden bzw. die Ursache behoben wird.

Inhaltliche Ursache

Inhaltliche Ursachen beziehen sich auf den Inhalt der versendeten Nachricht. Diese wird vom Zielsystem nicht verstanden wenn:

  • Wichtige Informationen fehlen
  • Die Validierung fehlschlägt
  • Nachricht enthält zusätzlichen, unverständlichen Inhalt
  • ...
Wird eine Nachricht mit inhaltenlichem Defekt erneut an den Consumer zugestellt, wird die Nachricht erneut abgelehnt. Da sich der Inhalt der Nachricht durch die erneute Zustellung nicht verändert, egal ob die Nachricht einmal, oder 100.000mal zugestellt wird.

Poison Acknownledge

Das Blockieren einer Queue durch Retries mit einer inhaltlich defekten Nachricht lässt sich durch Verwendung eines PoisonAcknowledge verhindern. Durch das PoisonAckownledge weiß der Broker dass die Nachricht nicht verstanden wurde, eine erneute Zustellung wird verhindert und die Nachricht sofort in eine DeadLetterQueue weitergeleitet.

Fazit

Ein Redelivery ist eine Art der hoffnungsvollen, automatisierten Fehlerbehandlung durch die Infrastruktur. Dies ermöglicht die Behandlung vieler Fehler, ohne dass eigener Error-Handling Code geschrieben werden muss.

Ist das System einige Zeit produktiv im Einsatz, könnte sich ein Blick in die DLQs des Brokers lohnen. Zeigen mehrere Nachrichten ein gemeinsames Problem, welches nach einem festen Schema abgearbeitet werden kann, kann das System mit einer automatisierten Fehlerbehandlung erweitert werden.

Quellen

  • [1] http://www.zeitblueten.com/news/zitate-albert-einstein/