1

我正在尝试从 Java 中的 MQ 队列中读取消息,当处理异常时需要回滚时,我对流程有点困惑。

我有一个循环运行并查找消息的阅读器类。当我初始化阅读器时,它会创建一个连接和一个会话。然后,当需要在循环中读取消息时,它会创建一个MQQueueand MQQueueReceiver。这工作正常,我从队列中得到一个 JMSMessage,然后将其交给另一个线程工作。如果工作线程失败,我想将该消息放回队列中(以便集群中的其他节点重试)。

我的问题是,我如何回滚?我注意到类rollback()中有一个方法MQQueueSession。但是我对我的所有消息都重用了同一个会话。我是否理解应该为每条消息创建一个新会话,而不是一遍又一遍地重复使用同一个会话?

这对我来说是反直觉的。

会话也是用connection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);. 我应该使用另一个标志,而不是CLIENT_ACKNOWLEDGE

4

2 回答 2

1

您应该使用 Session.SESSION_TRANSACTED 标志和 Session.commit/Sessiuon.rollback 来提交/回滚在当前事务中完成的所有消息

于 2013-04-18T14:49:50.207 回答
1

请注意,JMS 1.1 规范将会话定义为:

Session - 用于发送和接收消息的单线程上下文

后来在规范中说:

限制对 Session 的并发访问有两个原因。首先,Sessions 是支持事务的 JMS 实体。实现多线程事务非常困难。其次,Sessions支持异步消息消费。重要的是,JMS 不要求用于异步消息消费的客户端代码能够处理多个并发消息。此外,如果一个 Session 已经设置了多个异步消费者,重要的是不要强迫客户端处理这些单独的消费者同时执行的情况。这些限制使 JMS 更易于用于典型客户端。更复杂的客户端可以通过使用多个会话来获得他们想要的并发性。

所以,不,您不需要每条消息一个会话。但是,会话下生成或使用的所有消息都会一起提交或回滚,即使您已将它们移交给其他线程并且此行为符合规范。

使用 Evgeniy 描述的事务处理会话和 COMMIT/ROLLBACK,但也要注意将消息保持在同一会话范围内,所有这些都在同一工作单元内。

于 2013-04-19T19:29:47.850 回答