与JMS(ActiveMQ)一起使用事务

在我们的后端,有几个服务通过JMS与Apache ActiveMQ发送和接收消息.每个服务都有一个到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()
}

提交显然必须阻止,直到答案到达或交易失败.服务s2也应该可能创建一个新的嵌套事务,因为s2正在向另一个服务发送消息.如何使用ActiveMQ的事务来实现这种行为?有一些示例可用,但在这些示例中,事务仅用作发送消息的批处理机制.

最佳答案 我正在解释你的问题意味着你希望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的异步模型不是为此目的而经典设计的.根本原因是因为

>在事务资源(例如数据库记录)被锁定期间 – s1已完成一些工作,直到事务已解决,这些资源必须保持锁定状态.
> Asynch处理旨在将s2工作与s1工作分离,s2工作可能在请求放入队列后几分钟或几天内发生. S2无法知道s1是否还在等他. JMS的整个设计点是在s1和s2中解耦处理.

有两种方法可以实现s1和s2之间的协调:

一种是使用真正的分布式事务,使用除JMS之外的协议,例如EJB可以将事务从一个进程传播到另一个进程,或者使用WS-AtomicTransaction和Web服务.这确实增加了操作复杂性 – 您必须管理事务日志和一个组件长期失败的情况.

另一种方法是设计两个协作系统,以稳健地处理“补偿”工作.你接受这一点,例如s2可能会失败,并且有二次处理来处理重发请求,处理超时等.最后你可能会遇到人类需要参与的某些情况,但是如果设计良好,这些情况可能是最小的.在大型系统中,通常没有替代方案,例如航空公司的预订系统和连锁酒店的预订系统可能不适合分布式交易协调,因此除了经过一些精心处理以管理预订航班和房间之外别无选择.

点赞