我正在使用Spring JMS
和ActiveMQ
到JNDI
/ Tomcat
实现一个简单的演示。整个目的是拥有一个发送者和多个接收者,但队列中的消息必须同步操作,这意味着无论在原始发送顺序中应该处理多少个接收者,所有消息都应该被处理。
这就是我做的事情
创建一个可以通过队列通过ActiveMQ / Tomcat / JNDI发送和接收JMS消息的spring应用程序。我将@Transactional
放到onMessage()
方法(应该在JPA中工作,但可能不在此示例中)。 sender方法使用@Scheule注释,每5秒运行一次,并向队列发送10条消息。有一个全局计数器来计算发送的总消息。
部署此应用的三个实例,其中一个启用了发送方和接收方,另外两个只激活了接收方。那么所有三个接收器都会将消息写入相同的text file
(作为一个小型数据库工作),这样每个接收者都会在写完后关闭文件。
默认情况下,我没有以同步方式更改ActiveMQ和Spring JmsTemplate的任何同步设置。
这是我得到的结果
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}
很明显,从 messageBody 18和19(请滚动到右侧),他们打破了同步(消息18应该在消息19之前传递)。我想知道它是否是ActiveMQ的一些随机情况,或者它可能是设置的一些潜在问题,或者可能是它写在文本文件中,所以如果它在真实的数据库中,那么@Transactional可以保证同步
答案 0 :(得分:1)
不可能保持与多个接收器的严格排序(或单个接收器上的并发性> 1)。
消费者正在竞争消息,它只是一个竞争对象,它将处理它首先获得的下一条消息。操作系统可能会在收到消息后但在写入文件之前将一个线程从CPU中释放出来,而下一个"下一个"消费者可能会对整个事物进行端到端的处理。即使使用多核CPU,也会发生这种情况。