2012-02-20 56 views
4

在我們的後端,有幾個服務通過JMS與Apache ActiveMQ發送和接收消息。每個服務都有一個到ActiveMQ代理的會話。我們現在想要做以下(僞代碼):使用與JMS(ActiveMQ)交易

服務S1:

Message m = createMessage("s2","Hello World") 
sendMessage(m) 
try { 
    Message answer = commit() 
    ... 
} catch (TransactionFailedException e){ 
    ... 
} 

服務S2:

onMessageReceive: 
try { 
    Message m = getReceivedMessage() 
    Message answer = doSomeStuff() 
    send(answer) 
} (Exception e) { 
    rollback() 
} 

的承諾obviuosly有阻塞,直到答案到達或交易failes 。服務s2也應該有可能創建一個新的嵌套事務,因爲s2正在向另一個服務發送消息。如何使用ActiveMQ的事務來實現這種行爲?有一些示例可用,但在這些示例中,事務僅用作發送消息的批處理機制。

+0

您是否期待一項交易包含在s1和s2中完成的工作? – djna 2012-02-20 08:49:32

+0

是的,如果s2失敗,則交易在s1中失敗。 – problemzebra 2012-02-20 12:08:05

回答

2

我在解釋你的問題意味着你想在s2中導致正在進行的事務在s1中回滾失敗。

所以,你要

s1 do some work 

s2 do some work 

if (s2 OK) 
    perhaps do even more work in s1 
    commit s1 
else 
    rollback s1 

JMS的異步模型不是經典設計用於這一目的。根本原因是因爲

  1. 在事務資源(例如數據庫記錄)被鎖定 - s1已經做了一些工作,直到事務已經解決,這些資源必須保持鎖定。
  2. Asynch處理旨在將s2工作與s1工作分離,s2工作可能會在請求放入隊列後幾分鐘或幾天發生。 S2不知道s1是否還在等着他。 JMS的整個設計點是在s1和s2中解耦處理。

有兩種方法來s1和s2之間實現協調:

一種是使用真正的分佈式事務,使用除JMS以外的協議,例如EJB可以從一個過程事務傳播到另一個,或使用WS-AtomicTransaction和web服務。這確實增加了操作的複雜性 - 您必須處理事務日誌以及單個組件出現長期故障的情況。

另一種方法是設計兩個合作系統來強有力地處理「補償」工作。您接受,例如s2可能會失敗,並有二級處理來處理重發請求,處理超時等。最後,您可能會回到某些人類需要參與的情況,但通過良好的設計,這些情況可以是最小的。在大型系統中,通常沒有其他替代方案,例如,航空公司的預訂系統和連鎖酒店的預訂系統可能不適合分佈式事務協調,所以沒有其他選擇來進行精心處理來管理預訂航班和客房。

+0

感謝您的回答。這與我的預期相似。 – problemzebra 2012-02-20 12:07:17