4
votes

I have a .NET service that uses the ActiveMQ client. I have implemented a MessageListener with a transacted connection to consume the messages.

Occasionally, I get messages in a different order in which they were put onto the queue.

Was it wrong to use a MessageListner? Is there a way to preserve the message order?

FYI: There is one producer putting messages on the queue and one consumer pulling messages off the queue.

4
Please see this thread for a little more background on the issue stackoverflow.com/questions/269363/activemq-net-client-locks-upHitLikeAHammer

4 Answers

1
votes

You shouldn't have to do anything to maintain the order; that's one of the things that a message queue does for you. I would think that if you have a single consumer listening to the queue, and it is processing messages out of order, then you have either found a bug or the messages aren't enqueued in the order you think they are.

Also, there's this question from the ActiveMQ FAQ that might help.

Edit: From reading the comments on duffymo's answer, it looks like you're overengineering a bit. In general, a message queue like ActiveMQ, MQ Series, joram, etc. have two characteristics: they deliver messages in the same order in which they are enqueued, and they guarantee message delivery. Sending a separate ACK message is redundant; it's a bit like committing a database transaction, then querying the same information back to double-check that the database actually stored it.

Having said that, is your server multithreaded? If so it may possible for it to enqueue the response before it enqueues the ACK.

1
votes

More Info: The server I call is third party and I have no control over what messages it sends. I do know, based on the message ID's that they are put on in the right order. Also, in this system there is a difference between ACK and Acknowledge. The ACK is received when my original message is put on the the "outbound" queue. I then monitor an "inbound" queue for responses. I usually get an "Acknowledge" followed by a "Pass" or a "Fail". The correlation ID for these messages is the message ID from the ACK.

I had originally used a message listener and responded to an OnMessge event. I abandoned this approach after realizing that, using this method, messages are delivered asynchronously and therefore in no particular order. So, I changed my code to poll using a timer (System.Threading.Timer) to call consumer.Receive() and get one message at a time. This works the way I want.

I open the consumer once when the service starts and I continuously poll for messages.

0
votes

Why is message order important? A MessageListener shouldn't have to care.

If you need a correlation ID to match a response with a particular request, that's another matter. Is that what you mean?

0
votes

Everything Jason just said. A few other things to be careful of. You are keeping the consumer open for lots of messages right? You're not creating a consumer for a few messages then closing it? Only closing a consumer causes messages associated with a consumer to be put back onto a queue which can break order.

Is it related to rollbacks? (Are you rolling back any transactions?).

Finally, you can always ensure order by using a Resequencer to reorder things for you.