2014-11-24 68 views
0

我正在用Spring JMSActiveMQJNDI/Tomcat实现一个简单的演示。整个目的是让一个发送者和多个接收者,但队列中的消息必须同步操作,这意味着无论接收者有多少,所有的消息都应该按原始发送顺序处理。Spring JMS和ActiveMQ的同步问题

这是我做过什么

  1. 创建弹簧的应用程序,可以通过一个队列通过的ActiveMQ/Tomcat的/ JNDI发送和接收JMS消息。我把@Transactional改为onMessage()方法(假设可以在JPA中工作,但可能不在这个例子中)。 sender方法使用@Scheule进行注释,并且每5秒运行一次并向队列发送10条消息。有一个全球计数器来计算正在发送的总邮件。

  2. 部署此应用程序的三个实例,其中一个同时打开发送者和接收者,另外两个仅激活接收者。那么所有三个接收器都会将消息写入相同的text file(作为小型数据库使用),以便每个接收器在写入后都会关闭文件。

  3. 我没有更改任何同步设置为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} 

距离消息体18和19(请向右滚动)他们打破了同步(消息18消息前,应提供明显的结果19)。我想知道它是否仅仅是ActiveMQ的一些随机案例,或者它可能是一些设置的潜在问题,或者可能是写入文本文件,所以如果它在真实数据库中,那么@Transactional可以保证同步

回答

1

使用多个接收器保持严格排序是不可能的(或者在单个接收器上并发> 1)。

消费者正在竞争消息,它只是一个竞争,哪个人处理下一个消息。操作系统在获取消息之后但在写入文件之前可能会从CPU中脱离线程,而“下一个”消费者可能会先处理整个事件。即使使用多核CPU,也可能发生这种情况。

+0

谢谢。没有定单的竞争者可以在竞争对手中随机选择消息,这是可以的,但是在这种情况下,消息的输出至少应该与队列中最初的消息相同。我确定随机出现接收者,但请检查消息18和消息19的顺序是否错误。对不起,我应该在门票中突出显示它。 – Dreamer 2014-11-25 02:15:27

+0

你的测试没有提到生产者。它只是表明receiver2收到了消息18,receiver1收到了消息19 __at,并且接收方1碰巧赢得了在文件_中记录接收的竞赛。单个消费者的消息接收将按顺序进行,但并不保证消费者的下游处理将以任何顺序进行。所以实际上,接收者2 __did__在接收者1得到他的消息之前得到消息;他只是失去了首先将其写入文件的竞赛。如果将毫秒添加到日志配置中,则可能会更清晰一些,但可能不会。 – 2014-11-25 03:16:35

+0

hmm ....“单个消费者的消息接收将按顺序进行,但不存在这样的保证,即消费者的下游处理将以任何顺序发生。”现在我明白了,谢谢:) – Dreamer 2014-11-25 19:02:40