Processing JMS messages in sequence
Processing messages in sequence is a challenge in ESB.
We have a notion that message queue serves the messages in FIFO so sequence will be persevered. But that is not correct. In various situation messaging order will be violated.
Message Sequence Violation: Single Server with multiple threads
Message sequence may not be retained though JMS listener process is running in a single server.
When subscriber process run in single server environment, it may instantiate multiple subscriber instances when multiple messages are pushed by message broker. Each instances run in parallel independent of others. So messaging sequencing may be violated though message brokers sends the messages in sequence.
Workaround: Run the process in a single thread. Message broker connection parameter should be configured such a way that message broker deliver a single message at a time.
Message Sequence Violation: In server cluster environment, message sequence may not be retained, even when subscriber process may run in a single thread.
For cluster environment, connection will be made from multiple servers to the message broker.
Message broker normally sends the messages to the multiple subscribers, in round robin fashion. So in this case even though process running in single thread in servers, may violate FIFO sequence.
Workaround:
In this case broker connection should configured in such way that it sends the messages only to the single subscriber at a time. Or we can configure the connection in such way, that it send the messages to the subscriber which made first connection.
In cluster environment when connection is made from the both server, broker should ensure that messages are delivered to the single subscriber only. It will stick to the subscriber who makes the connection first, in spite of number of subscriber connected.
Message Sequence violation: messages could not be delivered due to connection failure, sever issue or business error.
In normal situation, suppose your process is delivering messages in sequence (fulfilling workaround that is described above two cases). Suppose, a message could not be delivered to the target due to connection issue or server issue or business error.
In this can we have to take decision, whether we should keep on trying to send the messages to the target to maintain sequencing. Keeping on trying may not be good idea, sometimes the messages can never be accepted by target due to business error. If you keep on trying to send such messages to the target, other messages will also be stuck. Also sometimes it is difficult to know if rejection happens due to business error or system error.
Workaround:
Best solution to handle such case is hybrid solution that is using Message Queue and Database combination.
If the message could not be sent to the target, send that message and subsequent messages to the database. Write a batch job which will try to post the records to the target after reading from the database (while reading records should be sorted on the basis of timestamp)
Best approach would be after couple of try, send notification to the business users. Let business user take care of the messages. They can decide if messages need to be retried or can be fixed.
Message subscriber process should do database look up and check if there is any record in the error table. In such cases all the subsequent messages should be sent to the database instead of sending to the target.
The batch processes which picks up the messages from database should run in a single thread.
This is inefficient way of handling sequencing. We should follow messaging grouping context described in below section.
Workaround: message group or set of records
For bad message handling, sending that particular message and all the subsequent messages in the database to maintain sequencing, might be a bad idea. So we should follow the concept of message group/set of records to manage sequencing. For example, we can group messages on the basis of customer id. Suppose a set of messages belongs to particular customer. So if a bad message belongs that customer, other messages of that customer along with that bad message, will be sent to the error table. Other customer’s messages will not be impacted. In the above diagram, message 2 of customer 2 have issue, so message 2 along with message 3 will be sent to the error table though message 3 is a good message.
When ESB gets a bad messages, only that particular message group will be impacted. This is a better solution.
.Group of messages processing in parallel
With message grouping, not only you can handle error situation better, also you can process multiple group of messages in parallel. Thus improving the overall efficiency. You can send separate message group in separate server. You can configure message broker in such way that it sends the message of same group on the same server. In this way, you can achieve parallel processing maintaining message sequence.
Conclusion:
Queue is not enough to manage message sequence in real life scenario. Best way is to use hybrid model (Message Queue + Database) and build custom solution.
When message could not be sent to the destination due to any issue, the message should be sent to error table.
Next for fresh messages coming to the queue, database lookup should be done to check if previous records already exist or not in the error table. If previous records exist, current record /message should not be sent to the destination and should be inserted to the database instead.
A batch job should run periodically to read the messages from the database. Messages should be sorted on the basis of timestamp.
Also you need to follow message grouping rules for parallel processing and for efficient processing of messages.