Ich habe ein Java-System, das ActiveMQ für Messaging verwendet. Das System verarbeitet ungefähr 400 bis 600 Transaktionen pro Sekunde und wir haben kein Problem, wenn alles reibungslos läuft. Das System muss diese Transaktionen auch an ein externes System senden.
Wenn das externe System längere Zeit nicht verfügbar ist (z. B. ein oder zwei Stunden), senden wir fehlgeschlagene Nachrichten, die während des Ausfalls nicht erfolgreich an das externe System gesendet wurden, an eine Warteschlange (was wir als Wiederholungswarteschlange bezeichnen). .
Wir müssen diese Nachrichten rechtzeitig verarbeiten, damit wir dem externen System ausreichend Zeit für die Wiederherstellung geben.
Wir haben verschiedene Ansätze ausprobiert und keiner scheint perfekt zu funktionieren. Die meisten von ihnen funktionieren, wenn wir weniger Nachrichten bearbeiten.
Ansatz 1: Wir haben die ActiveMQ-Verzögerung verwendet, bei der wir den Zeitstempel im JMS-Header festgelegt haben (weitere Informationen finden Sie hier: http://activemq.apache.org/delay-and-schedule-message-delivery.html ) Es gibt wie ein paar hundert oder tausend Nachrichten in der Warteschlange.
Wir haben einen Nachrichtenverlust festgestellt, wenn 500.000 oder mehr Nachrichten vorhanden waren. Wir haben festgestellt, dass Nachrichten auf mysteriöse Weise angezeigt werden, ohne uns einen Hinweis zu geben.
Ich sehe zum Beispiel, dass Nachrichten sogar für 20.000 Nachrichten verschwunden sind.
Wir stellen die Verzögerung auf 5 Minuten ein, damit Nachrichten in einer Stunde bis zu 12 Mal versucht werden. Wenn das externe System eine Stunde lang nicht verfügbar war, erwarteten wir, dass alle 20.000 Nachrichten mindestens 12 Mal wiederholt wurden.
Was wir beobachteten, war, dass wenn wir alle 5 Minuten konsumieren:
Versuch 1: 20k Nachrichten Versuch 2: 20k Nachrichten
Versuch 7: 19987 Nachrichten Versuch 10: 19960 Nachrichten Versuch 12: 19957 Nachrichten
Manchmal wurden alle 20.000 Nachrichten verarbeitet, aber die Testergebnisse waren inkonsistent.
Ansatz 2:
Wir haben die Redelivery-Richtlinie von ActiveMQ verwendet, bei der wir die Richtlinie auf der Ebene der Verbindungsfactory festgelegt, die Sitzung abgewickelt und eine Ausnahme ausgelöst haben, wenn das externe System ausgefallen ist, damit der Broker die Nachrichten basierend auf der Konfiguration der Redelivery-Richtlinie weiterhin erneut liefert. Auch dieser Ansatz hat nicht gut funktioniert, wenn der Ausfall länger andauert und wir keine nicht blockierenden Verbraucher haben müssen. Es funktioniert auf der Ebene der Versandwarteschlange selbst und belastet die Warteschlange, wenn viele Transaktionen eingehen.
Ansatz 3:
Wir haben den Quartz Scheduler verwendet, der alle X Minuten aufwacht und eine Verbindung herstellt. Die Verbraucher können Nachrichten aus der Wiederholungswarteschlange abrufen, versuchen, sie weiter zu verarbeiten. Wenn das externe System immer noch inaktiv ist, stellen sie die fehlgeschlagene Nachricht in den hinteren Bereich der Warteschlange. Dieser Ansatz hat viele Probleme, so dass wir gezwungen waren, Verbindungen, Verbraucher usw. zu verwalten.
Wenn sich beispielsweise mehrere Nachrichten in der Warteschlange befinden und mehr Verbraucher als die Anzahl der Nachrichten vorhanden sind, hat dies dazu geführt, dass eine Nachricht von einem Verbraucher abgeholt wurde. Wiederum hat derselbe Verbraucher die Nachricht wieder in "Wiederholen" abgelegt (als Das externe System ist immer noch inaktiv), und ein anderer Verbraucher nimmt es auf, was dazu führt, dass Nachrichten zwischen Verbraucher und Broker hin und her übertragen werden.
Ansatz 4:
Wir haben versucht, die fehlgeschlagenen Nachrichten in der Datenbank zu speichern, und den Quarz-Scheduler alle X Minuten ausführen lassen, um die Nachrichten aus der Datenbank abzurufen.
Dies ist nicht optimiert, da es viele Transaktionsprüfungen zwischen DB-Verbrauchern erfordert, die auf mehreren Knoten ausgeführt werden, und der DB.
Meine Umgebung ist Java, JBoss, ActiveMQ 5.9, MySQL 5.6 und Spring 3.2.
Ich habe verschiedene andere Ansätze durchlaufen, wie z. B. die Wiederholungsvorlage (von Spring) und das asynchrone Wiederholungsmuster mit Java 7/8
Meiner Meinung nach funktionieren die meisten Lösungen bei minimaler Auslastung und scheinen zu brechen, wenn der Ausfall länger dauert oder wenn das Nachrichtenvolumen sehr hoch ist.
Ich suche etwas, in dem ich fehlgeschlagene Nachrichten speichern und weiterleiten kann. Für ein 400-TPS-System kann ich in einer Stunde 1,44 Millionen Nachrichten haben.
Wenn das externe System ausfällt, wie verarbeite ich diese 1,44 Millionen Nachrichten, sodass jede Nachricht die gleiche Chance hat, erneut versucht zu werden, ohne dass Nachrichten oder Leistung verloren gehen.
Ich suche nach einer Lösung im Rahmen meiner Umgebung.