Ho un sistema Java che utilizza ActiveMQ per la messaggistica. E il sistema elabora da 400 a 600 transazioni al secondo e non abbiamo alcun problema quando tutto procede senza intoppi. Il sistema ha anche potuto inviare queste transazioni a un sistema esterno.
Quando il sistema esterno è inattivo per un periodo di tempo prolungato (ad esempio un'ora o due), ciò che facciamo è che eliminiamo i messaggi non riusciti che non sono stati inviati correttamente al sistema esterno durante l'interruzione di una coda (ciò che chiamiamo Nuovo tentativo).
Dobbiamo elaborare questi messaggi in modo tempestivo in modo da offrire al sistema esterno tutto il tempo necessario per il ripristino.
Abbiamo provato diversi approcci e nessuno sembra funzionare perfettamente. Molti di questi funzionano quando gestiamo un minor numero di messaggi.
Metodo 1: Abbiamo utilizzato il ritardo ActiveMQ in cui abbiamo impostato la data / ora nell'intestazione JMS (vedere qui per ulteriori dettagli: link ) e ha funzionato quando ci sono come poche centinaia o migliaia di messaggi in coda.
Abbiamo rilevato una perdita di messaggi quando c'erano circa 500 o più messaggi. Abbiamo trovato che i messaggi appaiono misteriosamente senza darci alcun indizio.
Ad esempio, vedo che i messaggi sono scomparsi anche per i messaggi 20k.
Impostiamo il ritardo su 5 minuti in modo che i messaggi vengano provati per un massimo di 12 volte in un'ora. Quando il sistema esterno è rimasto inattivo per un'ora, ci aspettavamo che tutti i 20k messaggi fossero riprovati almeno per 12 volte.
Ciò che abbiamo osservato è che quando consumiamo ogni 5 minuti:
Tentativo 1: 20k messaggi Tentativo 2: 20k messaggi
Tentativo 7: 19987 messaggi Tentativo 10: 19960 messaggi Tentativo 12: 19957 messaggi
A volte venivano elaborati tutti i messaggi 20k ma i risultati del test erano incoerenti.
Approccio n. 2:
Abbiamo utilizzato i criteri di riconsegna di ActiveMQ in cui impostiamo il criterio a livello di factory di connessione, rendiamo transazionale la sessione, generiamo un'eccezione quando il sistema esterno è inattivo, in modo che il broker continui a riconsegnare i messaggi in base alla configurazione del criterio di riconsegna. Anche questo approccio non ha funzionato bene quando l'interruzione dura per una durata maggiore e abbiamo bisogno di avere consumatori non bloccanti. Funziona a livello di coda di invio stesso, mettendo a dura prova la coda quando ci sono molte transazioni in entrata.
Approccio n. 3:
Abbiamo usato il programma di pianificazione Quartz che si sveglia ogni X minuti e crea una connessione, i consumatori ottengono i messaggi dalla coda Retry, provano a elaborarli ulteriormente e se il sistema esterno è ancora inattivo, mettono il messaggio fallito sul retro del coda. Questo approccio ha molti problemi tali da costringerci a gestire connessioni, consumatori, ecc.
Ad esempio, quando ci sono un paio di messaggi nella coda, quando abbiamo più consumatori del numero di messaggi, il risultato è stato un messaggio raccolto da un consumatore, di nuovo lo stesso utente che ha scaricato il messaggio in Retry (mentre il sistema esterno è ancora inattivo) con un altro consumatore che lo raccoglie, con conseguente viaggio di andata e ritorno del messaggio tra Consumer e Broker.
Approccio n. 4:
Abbiamo provato a memorizzare i messaggi non riusciti nel DB e fare in modo che lo scheduler del quarzo venga eseguito ogni X minuti per raccogliere i messaggi dal DB.
Questo non è ottimizzato e comporta un sacco di controllo delle transazioni tra gli utenti di DB in esecuzione su più nodi e sul DB.
Il mio ambiente è Java, JBoss, ActiveMQ 5.9, MySQL 5.6 e Spring 3.2.
Sono passato attraverso diversi altri approcci, come Retry template (da Spring) e Asynchronous Retry pattern con Java 7/8
La mia opinione sul problema è che la maggior parte delle soluzioni funziona quando c'è un carico minimo e sembrano interrompersi quando l'interruzione dura più a lungo o quando il volume dei messaggi è molto alto.
Sto cercando qualcosa in cui posso archiviare e inoltrare messaggi non riusciti. Per un sistema 400 TPS, in un'ora, potrei avere 1,44 milioni di messaggi.
Se il sistema esterno non funziona, allora come elaborerò questi 1,44 milioni di messaggi dando a ciascun messaggio la stessa possibilità di essere riproposto senza perdere messaggi o prestazioni.
Sto cercando una soluzione nel campo di applicazione dell'ambiente che ho.