Spring JMS和ActiveMQ的同步问题

时间:2014-11-24 22:08:38

标签: spring jms activemq spring-jms

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

这就是我做的事情

  1. 创建一个可以通过队列通过ActiveMQ / Tomcat / JNDI发送和接收JMS消息的spring应用程序。我将@Transactional放到onMessage()方法(应该在JPA中工作,但可能不在此示例中)。 sender方法使用@Scheule注释,每5秒运行一次,并向队列发送10条消息。有一个全局计数器来计算发送的总消息。

  2. 部署此应用的三个实例,其中一个启用了发送方和接收方,另外两个只激活了接收方。那么所有三个接收器都会将消息写入相同的text file(作为一个小型数据库工作),这样每个接收者都会在写完后关闭文件。

  3. 默认情况下,我没有以同步方式更改ActiveMQ和Spring JmsTemplate的任何同步设置。

  4. 这是我得到的结果

    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可以保证同步

1 个答案:

答案 0 :(得分:1)

不可能保持与多个接收器的严格排序(或单个接收器上的并发性> 1)。

消费者正在竞争消息,它只是一个竞争对象,它将处理它首先获得的下一条消息。操作系统可能会在收到消息后但在写入文件之前将一个线程从CPU中释放出来,而下一个"下一个"消费者可能会对整个事物进行端到端的处理。即使使用多核CPU,也会发生这种情况。