Reliability- und Performance-Testing einer Message-Bridge-Plattform

Wie lässt sich die Zuverlässigkeit einer hochverfügbaren Messaging Plattform testen? Dieser Beitrag beschreibt am Anwendungsfall eines Kunden, auf welche Art und Weise die Zuverlässigkeit geprüft werden kann und welche Tools dabei zum Einsatz kommen.

Anforderungen

  • Die bestehende Messaging Plattform, basierend auf HornetQ und Websphere MQ, soll durch eine hochverfügbare ActiveMQ-Umgebung ersetzt werden.
  • Die beteiligten Applikationen sollen schrittweise migriert werden.

Somit kann es vorkommen, dass Consumer und Producer nicht auf demselben Messaging-System basieren. Um die Kommunikation trotzdem zu gewährleisten, wird eine Messaging Bridge (vgl. Enterprise Integration Pattern) eingesetzt.

Overview

 

(Übersicht der Messaging-Plattform)

Umsetzung

  • Die Messaging-Bridge wird mit Apache Camel und den Resource Adaptern (RAR) für die beteiligten Message-Systemen auf JBoss EAP 6.3 realisiert.
  • Die hohe Verfügbarkeit wird mit Redundanz und Failover der Broker garantiert.
  • Um ein zuverlässiges Messaging zu garantieren, werden die Messages auf der Bridge über eine verteilte Transaktion mittels eines Zwei-Phasen-Commit-Protokolls (2PC) zwischen den beteiligten Brokern übertragen.

Testing

Reliability Tests

In verteilten Systemen kann es zu Netzwerk- und Serverausfällen kommen, die wiederum zu Message-Verlusten und -Duplikaten führen können. Mit 2PC können solche Dateninkonsistenzen vermieden bzw. korrigiert werden.

Ob die Messaging-Bridge in Bezug auf 2PC richtig konfiguriert ist und die Implementation sich auch wie erwünscht verhält, soll mittels Reliability-Tests geprüft werden. Zum Beispiel kann ein Ausfall der beteiligten Systemen zu unterschiedlichen Zeitpunkten simuliert werden. Nach einem Neustart der Server und einem allfälligen Recovery, müssen die Daten wieder in einem konsistenten Zustand vorliegen.

Das folgende Sequenzdiagramm zeigt, wie eine persistente Message von einem Broker (B1) über die Bridge zu einem zweiten Broker (B2) übertragen wird. Im Anschluss erfolgt der Zwei-Phasen-Commit, wobei die Bridge ausfällt, bevor der Commit an den zweiten Broker erfolgen kann. Im beschriebenen Szenario handelt es sich um einen Ausfall des Koordinators. Nach einem Neustart der Bridge muss ein TX-Recovery stattfinden, das die Transaktion abschliesst, sonst bleibt die Message auf Broker 2 blockiert.

coordinator-failure

 

(Koordinator-Ausfall)

Nebst dem Ausfall des Koordinators sind auch Ausfälle von Teilnehmern und eine Partitionierung des Netzwerks denkbar. Die beiden folgenden zwei Sequenzdiagramme zeigen einen Ausfall eines Brokers. Bei beiden Szenarien erhält der Koordinator kein ack(). Im ersten Fall ist die Transaktion auf Persistent-Message-Store-Seite schon abgeschlossen, im zweiten Fall noch nicht. In beiden Fällen soll nach dem Recovery die Message nur genau einmal über die Bridge zum zweiten Broker übertragen worden sein. Bei einer normalen (nicht XA) transaktionalen JMS-Session wäre ein Redelivery im ersten Fall denkbar.

Um die oben beschriebenen Szenarien simulieren zu können eignen sich von Hand initiierte und dadurch zufällig gewählte Zeitpunkte in der Verarbeitung nicht, denn die Zeitspanne der kritischen zweiten Phase wird vom Protokoll bewusst möglichst kurz gehalten. Somit müssen andere Möglichkeiten gesucht werden, mit denen der gewünschte Ausfall deterministisch herbeigeführt werden kann. Eine Möglichkeit wäre, den Sourcecode so zu modifizieren, dass das gewünschte Fehlverhalten auftritt. Dieses Vorgehen hat jedoch den Nachteil, dass neu kompiliert und deployed werden muss. In den obigen Szenarien befinden sich zudem die zu modifizierenden Codestellen im Source von JBoss EAP respektive des Brokers was den Austausch der Binaries zusätzlich erschwert.

paricipant-commit-success-reply-lost

(Commit erfolgreich, Antwort verloren)

paricipant-commit-lost-reply-lost

(Commit verloren, Antwort verloren)

Mit Byteman lässt sich Java-Code zur Laufzeit verändern. Somit muss weder ein künstlicher Fehlerfall in die originalen Sourcen eingeschleust werden, noch neu kompiliert und deployed werden. Fremdcode lässt sich gleichermassen manipulieren, was für die aufgezeigten Fehlerfälle besonderes nützlich ist, denn die Transaktionen werden von der jeweiligen Plattform (EAP, Fuse) gemanaged und sind somit nicht Bestandteil des Anwendungscodes.

Das nachfolgende Code-Snippet zeigt ein Byteman-Script, das auf Brokerseite (in diesem Fall JBoss A-MQ 6.1) die JVM beendet, bevor in der zweiten Phase die Transaktion persistiert werden kann.

RULE Lets JBoss Fuse and A-MQ crash during 2nd Phase of a 2PC
 CLASS org.apache.activemq.transaction.XATransaction
 METHOD storeCommit
 AT EXIT
 # check if second phase of 2PC
 IF $2
 DO traceln("Killing VM during 2nd phase of 2PC"), killJVM()
 ENDRULE

Legende:

RULE: Eindeutige Bezeichnung der Regel
CLASS: Voll-qualifizierter Klassenname
METHOD: Name der Methode
AT EXIT: Am Ende der Methode
IF $2: Wenn das zweite Argument der Methode true ist, in dem Fall, wenn
die zweite Phase des Commits durchgeführt wird
DO. . . : Meldung ausgeben danach JVM beenden

Mit dem Script lässt sich das Verhalten aus Sequenzdiagramm 3 reproduzieren. Durch leichte Modifikation von AT EXIT zu AT ENTRY lässt sich auch Sequenzdiagram 4 umsetzen.

Performance Tests

Die Performance der Messaging-Plattform wird von vielen verschiedenen Faktoren wie z.B. der Netzwerktopologie, der Hardware, der Message-Grösse und der Anzahl Producer beeinflusst. Mit Apache JMeter lassen sich über lange Zeiträume Messungen unter Beinflussung der oben genannten Faktoren erheben und in Diagrammen und Tabellen darstellen.

Mit zunehmender Last lassen sich Probleme in der Konfiguration wie z.B. der der Producer- und Consumer-Flow-Control erkennen. In der zugrunde liegenden Oracle-Datenbank des ActiveMQ-Brokers zeigte sich so auch, dass bei vielen grossen Messages die INSERTs und DELETEs die LOB Storage zum Überlaufen brachten.

Fazit

Das Testing von 2PC ist komplex, da für reproduzierbare Testabläufe Teile des Code des Plattform-Transaction-Managers analysiert und verstanden werden müssen. Bei den Performace-Tests zeigt sich, dass XA wesentlich weniger Durchsatz bringt als normales transaktionales Messaging. Daher kann für performance-kritische Anwendungen normales transaktionales Messaging in Kombination mit Idempotent Consumer die bessere Wahl sein.

JBoss Byteman ist das ideale Hilfsmittel, um den Ausfall eines Systems zu simulieren und das Verhalten im Fehlerfall zu testen ohne dabei den Code neu kompilieren und deployen zu müssen.

Kommentare sind geschlossen.