【问题标题】:Using transactions with JMS (ActiveMQ)将事务与 JMS (ActiveMQ) 一起使用
【发布时间】:2012-03-10 14:56:31
【问题描述】:

在我们的后端,有几个服务通过 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 的事务来实现这种行为?有一些可用的示例,但在这些示例中,事务仅用作发送消息的批处理机制。

【问题讨论】:

  • 您是否希望单个事务包含在 s1 和 s2 中完成的工作?
  • 是的,如果 s2 失败,事务应该在 s1 中失败。

标签: transactions jms activemq middleware


【解决方案1】:

我将您的问题解释为您希望 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. 异步处理旨在将 s2 工作与 s1 工作分离,s2 工作可能会在请求放入队列后几分钟甚至几天发生。 S2 不知道 s1 是否还在等他。 JMS 的整个设计点是解耦 s1 和 s2 中的处理。

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

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

另一种方法是设计两个协作系统以稳健地处理“补偿”工作。您接受,例如 s2 可能会失败,并且有二次处理来处理重新发送请求、处理超时等。最后,您可能会遇到一些需要人工参与的情况,但是通过良好的设计,这些情况可以是最小。在大型系统中,通常没有其他选择,例如航空公司的预订系统和连锁酒店的预订系统可能不是为分布式事务协调而设计的,因此除了进行一些仔细的处理来管理预订航班和房间之外别无选择。

【讨论】:

  • 感谢您的回答。这与我的预期相似。
猜你喜欢
  • 2013-01-11
  • 2010-09-09
  • 1970-01-01
  • 1970-01-01
  • 2015-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多