0
votes

I am implementing a simple demo with Spring JMS and ActiveMQ through JNDI/Tomcat. The whole purpose is to have one sender and multiple receivers but messages on the queue must be operated in synchronization, meaning no matter how many receivers all messages should be processed in the original sending order.

This is what I did

  1. Create a spring app that can send and receive JMS messages via ActiveMQ/Tomcat/JNDI through a queue. I put @Transactional to onMessage() method(supposed to work in JPA but may not in this sample). The sender method is annotated with @Scheule and will run every 5 seconds and send 10 messages to the queue. There is a global counter to calculate the total message being sent.

  2. Deploy three instances of this app, one with both sender and receiver turned on and the other two only activate the receiver. so then all three receiver will write the message into the same text file(working as a small database) so that every receiver will close the file after writing.

  3. I didn't change any synchronization settings as ActiveMQ and Spring JmsTemplate by default working in synchronized manner.

and here is the result I got

Mon Nov 24 13:57:00 EST 2014    Receiver 1  {from Sender agent..message_aj9gg95q1kmb77i8506bcn3dpp(0)=messageBody1}
Mon Nov 24 13:57:00 EST 2014    Receiver 0  {from Sender agent..message_aj9gg95q1kmb77i8506bcn3dpp(1)=messageBody2}
Mon Nov 24 13:57:00 EST 2014    Receiver 1  {from Sender agent..message_aj9gg95q1kmb77i8506bcn3dpp(2)=messageBody3}
Mon Nov 24 13:57:00 EST 2014    Receiver 1  {from Sender agent..message_aj9gg95q1kmb77i8506bcn3dpp(3)=messageBody4}
Mon Nov 24 13:57:00 EST 2014    Receiver 0  {from Sender agent..message_aj9gg95q1kmb77i8506bcn3dpp(4)=messageBody5}
Mon Nov 24 13:57:00 EST 2014    Receiver 1  {from Sender agent..message_aj9gg95q1kmb77i8506bcn3dpp(5)=messageBody6}
Mon Nov 24 13:57:00 EST 2014    Receiver 0  {from Sender agent..message_aj9gg95q1kmb77i8506bcn3dpp(6)=messageBody7}
Mon Nov 24 13:57:00 EST 2014    Receiver 1  {from Sender agent..message_aj9gg95q1kmb77i8506bcn3dpp(7)=messageBody8}
Mon Nov 24 13:57:00 EST 2014    Receiver 0  {from Sender agent..message_aj9gg95q1kmb77i8506bcn3dpp(8)=messageBody9}
Mon Nov 24 13:57:00 EST 2014    Receiver 1  {from Sender agent..message_aj9gg95q1kmb77i8506bcn3dpp(9)=messageBody10}
Mon Nov 24 13:57:05 EST 2014    Receiver 1  {from Sender agent..message_n7ofp65ioqcfhdl63cjg76e4fb(0)=messageBody11}
Mon Nov 24 13:57:05 EST 2014    Receiver 0  {from Sender agent..message_n7ofp65ioqcfhdl63cjg76e4fb(1)=messageBody12}
Mon Nov 24 13:57:05 EST 2014    Receiver 0  {from Sender agent..message_n7ofp65ioqcfhdl63cjg76e4fb(2)=messageBody13}
Mon Nov 24 13:57:05 EST 2014    Receiver 1  {from Sender agent..message_n7ofp65ioqcfhdl63cjg76e4fb(3)=messageBody14}
Mon Nov 24 13:57:05 EST 2014    Receiver 0  {from Sender agent..message_n7ofp65ioqcfhdl63cjg76e4fb(4)=messageBody15}
Mon Nov 24 13:57:05 EST 2014    Receiver 1  {from Sender agent..message_n7ofp65ioqcfhdl63cjg76e4fb(5)=messageBody16}
Mon Nov 24 13:57:05 EST 2014    Receiver 1  {from Sender agent..message_n7ofp65ioqcfhdl63cjg76e4fb(6)=messageBody17}
Mon Nov 24 13:57:05 EST 2014    Receiver 1  {from Sender agent..message_n7ofp65ioqcfhdl63cjg76e4fb(8)=messageBody19} ----- oops    
Mon Nov 24 13:57:05 EST 2014    Receiver 2  {from Sender agent..message_n7ofp65ioqcfhdl63cjg76e4fb(7)=messageBody18} ----- oops   
Mon Nov 24 13:57:05 EST 2014    Receiver 0  {from Sender agent..message_n7ofp65ioqcfhdl63cjg76e4fb(9)=messageBody20}

It is obvious from messageBody 18 and 19 (Please scroll to the right) they break the synchronization(message 18 should deliver before message 19). I wonder if it just some random cases by ActiveMQ or it could be some potential problem with the settings or, may be it is written in the text file so if it is in real database so the @Transactional can guarantee the synchronizaion

1

1 Answers

1
votes

It's impossible to retain strict ordering with multiple receivers (or concurrency > 1 on a single receiver).

The consumers are competing for messages and it's simply a race as to which one processes the next message it gets first. The OS might kick a thread off the CPU after it gets the message but before it writes the file, while the "next" consumer might get to process the whole thing end to end. This can happen even with a multi-core CPU.