Wiederholen Sie das Design für hohe Lautstärke


8

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.

Antworten:


1

Hier geht es um die Drosselung. Wenn das System hochgefahren wird, muss die Anwendung so gestaltet sein, dass sie weder für den Herausgeber noch für den Verbraucher überfordert ist.

Sie könnten mit Ihrem Algorithmus klug werden. Wenn Sie die Möglichkeit haben, eine Nachricht nach Priorität zu klassifizieren, können die fehlgeschlagenen Nachrichten mit einer niedrigeren Priorität gespeichert werden. Nachdem der Herausgeber eine neue Nachricht veröffentlicht hat, kann er in der Warteschlange mit niedrigerer Priorität prüfen, ob fehlgeschlagene Nachrichten erneut veröffentlicht werden müssen, und sie erneut veröffentlichen.

Dies ist ein bekannter Ansatz zum Drosseln von Nachrichten. Ich bin sicher, dass es andere Drosselungsalgorithmen gibt, die hier basierend auf Ihren spezifischen Anforderungen angewendet werden können.


0

Hier ist die Annahme, dass jeder Knoten eine Nachrichtenwarteschlange hat und alle diese Knoten eine DB verwenden. Alle diese Knoten versuchen, Nachrichten an ein externes System zu senden.

Eine geringfügige Änderung des dritten Ansatzes kann funktionieren.

  1. Wenn ein Knoten eine Tabelle erstellt, um nur neue Nachrichten zu speichern, falls das externe System ausfällt. Nehmen wir an, Knoten1 hat die Tabelle messages_node1 zum Speichern von Nachrichten erstellt.

Wenn 3 Knoten plötzlich ausgeführt werden und das externe System plötzlich ausfällt, sollte jeder Knoten neu ankommende Nachrichten in der entsprechenden Tabelle speichern, anstatt sie in MQ in die Warteschlange zu stellen. Halten Sie nicht zugestellte Nachrichten in der Warteschlange selbst. So viel Zeit Das externe System muss wiederhergestellt werden. Die vorhandene Messaging-Warteschlange wird nicht geladen. Sobald der Knoten erkennt, dass das externe System aktiv ist, werden die Nachrichten aus der entsprechenden Tabelle in die Warteschlange gestellt.

Dieser Ansatz löst viele Probleme. 1. Er hängt nicht von der Wiederherstellungszeit des externen Systems ab. 2. Er stürzt nicht ab, wenn zu viele eingehende Nachrichten eingehen, während das externe System ausfällt. 3.Konflikte zwischen Knoten werden minimiert, da jeder Knoten eine eigene Tabelle hat. 4. Die Reihenfolge der Nachrichten bleibt bis zu einem gewissen Grad erhalten.

Sie können APIs schreiben, um diese Ereignisse auszulösen. Jede Korrektur mit der obigen Antwort

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.