2010-07-13 17 views
6

Uso ActiveMQ come broker per recapitare i messaggi. Questi messaggi sono intenti per essere scritti in un dabatase. A volte, il database è irraggiungibile o inattivo. In tal caso, desidero ripristinare il mio messaggio per riprovare più tardi questo messaggio e voglio continuare a leggere altri messaggi.ActiveMQ: dead letter queue mantiene l'ordine dei miei messaggi

Questo codice funziona bene, tranne un punto: il messaggio annullate da una rollback mi sta bloccando dalla lettura degli altri:

private Connection getConnection() throws JMSException { 
    RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy(); 
    redeliveryPolicy.setMaximumRedeliveries(3); // will retry 3 times to dequeue rollbacked messages 
    redeliveryPolicy.setInitialRedeliveryDelay(5 *1000); // will wait 5s to read that message 

    ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, password, url); 
    Connection connection = connectionFactory.createConnection(); 
    ((ActiveMQConnection)connection).setUseAsyncSend(true); 
    ((ActiveMQConnection)connection).setDispatchAsync(true); 
    ((ActiveMQConnection)connection).setRedeliveryPolicy(redeliveryPolicy); 
    ((ActiveMQConnection)connection).setStatsEnabled(true); 
    connection.setClientID("myClientID"); 
    return connection; 
} 

creo la mia sessione in questo modo:

session = connection.createSession(true, Session.SESSION_TRANSACTED); 

rollback è facile chiedere :

session.rollback(); 

Immaginiamo ho 3 messaggi nella mia coda:

1: ok 
2: KO (will need to be treated again : the message I want to rollback) 
3: ok 
4: ok 

mio consumatore farà (sequenza lineare):

commit 1 
rollback 2 
wait 5s 
rollback 2 
wait 5s 
rollback 2 
put 2 in dead letter queue (ActiveMQ.DLQ) 
commit 3 
commit 4 

Ma io voglio:

commit 1 
rollback 2 
commit 3 
commit 4 
wait 5s 
rollback 2 
wait 5s 
rollback 2 
wait 5s 
put 2 in dead letter queue (ActiveMQ.DLQ) 

Quindi, come posso configurare il mio consumo di ritardare i miei messaggi annullate da una rollback più tardi?

risposta

8

Questo in realtà è un comportamento previsto, perché i tentativi di messaggi sono gestite dal cliente, non il broker. Quindi, dato che hai 1 sessione vincolata, e il tuo criterio di riprova è impostato per i 3 tentativi prima di DLQ, allora l'intero processo di ripetizione blocca quel particolare thread.

Quindi, la mia prima domanda è che se l'inserimento del database fallisce, non si aspetterebbe che tutti gli altri inserimenti DB falliscano per un motivo simile?

In caso contrario, il modo per aggirare è quello di impostare il criterio di riprova per tale coda su 0 tentativi, con un DLQ specifico, in modo che i messaggi non riusciranno immediatamente e andare nel DLQ. Quindi eseguire un altro processo che preleva il DLQ ogni 5 secondi e rielabora e/o reinserisce nella coda principale per l'elaborazione.

+0

grazie per la chiara spiegazione del comportamento. Abbiamo finalmente scelto RabbitMQ come broker e implementato il DLQ da soli. –

0

Si sta utilizzando <strictOrderDispatchPolicy /> nel file di configurazione XML ActiveMQ? Non sono sicuro che ciò influirà sull'ordine dei messaggi per la riconsegna o meno. Se stai utilizzando un ordine di spedizione rigoroso, prova a commentare tale criterio per vedere se questo cambia il comportamento.

Bruce

+0

No, non sto usando questa politica. Grazie per il link. –

0

Ho avuto lo stesso problema, non ho trovato la soluzione qui, quindi ho deciso di postarlo qui dopo averne trovato uno per le persone alle prese con lo stesso. Questo è fissato prima della versione 5.6 quando si imposta nonBlockingRedelivery proprietà su true in produzione connessioni:

<property name="nonBlockingRedelivery" value="true" />