2012-02-20 90 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