Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to guarantee JMS reliable delivery

I think plenty of (Spring in my case) applications using JMS may follow this workflow:

Database A ===> Producer ===> JMS Queue ===> Consumer ===> Database B

then reliability is a concern. Let's say if when a data record in Database A should always be marked as delivered, when the message contains the data record is truely consumed and persist the data in Database B. Then there are questions:

  1. From my knowledge, currently JMS protocol does not define any functions to send acknowledgement from consumer to producer, but only to MOM, so the actual consumer-to-producer acknowledgement methods vary by JMS provider. So does it mean there is no way to develop a mechanism for such acknowledgement that can work for generally all JMS products(ActiveMQ, WebSphere MQ and Jboss MQ)?

  2. Consider the scenario of a blackout, then does it make the messages in the queue just evaporate so need to resend? or different JMS products can pick up what is left, as the messages are Serialized, so that missing message can be only caused by transaction management or async/sync configuration but not because of application server is down?

like image 876
Dreamer Avatar asked Oct 29 '14 20:10

Dreamer


1 Answers

JMS guarantees the delivery of the message by nature, if the message is posted, then it will delivered to a consumer if there is one, whatever happen, the MOM is designed to ensure this fact. Anyway, delivered does not necessary mean processed.

Reliability is ensured by various mechanism :

  • the first one is the persistence of message in the queue (the queue AND the message must be flagged as persistent, which is the default value) which ensure that message will not be lost in case of system interruption.
  • then you have the acknowledgement and the retry policy, message will be kept in the queue until consumer acknowledge it and in case of transacted session, will be redelivered until consumer effectively processed the message or max retry is reached. Failed message can then be redirected to a dead letter queue for analysis.

To ensure the coherency between the two datasources you have to use XA transaction at least on the producer side (you have at least 2 resources implied in the transaction database A and JMS queue) in order to guarantee that the message will not be posted to the queue if the commit in database A fails or the database will not be updated if the post to the queue fails. Message consumption should be transacted too to ensure redelivery in case of rollback.

The transaction boundaries will never include both consumer and producer because it conflicts with the asynchronous nature of the messaging system, you can't afford to lock the resources on the producer side until the consumer process the message because you have no guarantee on when it will happen.

NB : in the event that your database does not support XA (or to improve performance) and if you have only 2 resources implied in the transaction (database and JMS queue) you can have a look to Logging Last Resource Transaction Optimization

like image 70
Gab Avatar answered Oct 18 '22 21:10

Gab