2014-11-24 74 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