多线程

时间:2016-09-23 06:38:11

标签: java multithreading transactions spring-amqp spring-rabbitmq

我正在使用Spring AMQP(RabbitMQ实现),我正在尝试将单个事务传播到多个线程中。

作为一个例子,假设有3个队列,名称为X,Y,Z,首先我使用thread-1从队列X获取消息,然后,该消息被赋予thread-0,并且克隆了thread-0消息,并通过thread-3将线程2和队列Z发送到队列Y. Thread-0等待thread-3和thread-4的完成,以提交或回滚消息。请注意,我在这里使用4个线程。

我想要的是基本上处理这3个操作(获取消息并将其放入两个队列)作为单个事务。即如果我成功将消息发送到队列Y,但未能将其发送到Z,那么发送给Y的消息将被回滚,原始消息也将回滚到队列X中。

到目前为止,我已经设法通过threadLocals(主要是TransactionStatus和TransactionSynchronizationManager.resources)来处理事务信息,并且我能够将这3个操作绑定到一个事务中。

但我的问题是将ACK / NACK发送到原始队列X,即使我提交/回滚事务,它只适用于队列Y和Z.从X获得的消息始终处于Unacked状态。

我尝试过channel.basicAck(),RabbitUtils.commitIfNecessary(),接近但没有成功。

请注意,我也启用了channelTransacted。任何帮助都非常感谢。

1 个答案:

答案 0 :(得分:1)

Spring事务绑定到单个线程。您可以直接使用RabbitMQ客户端使其工作 - 但您必须在所有线程之间共享相同的通道。但是,RabbitMQ documentation强烈建议不要这样做:

  

不得在线程之间共享通道实例。应用程序应该更喜欢每个线程使用一个Channel,而不是跨多个线程共享相同的Channel。虽然通道上的某些操作可以安全地同时调用,但有些操作并不会导致错误的帧交错。 ...

在任何情况下,即使您在单个线程上完成工作,RabbitMQ事务也相当薄弱,并不能保证很多;见broker semantics

  

AMQP仅在事务涉及单个队列时保证原子性,即tx内的所有发布都被路由到单个队列,并且所有acks都与从同一队列消耗的消息相关。 ...