我正在尝试用Java中的MQ队列读取消息,当处理异常时回滚时,我对流程有点困惑。
我有一个读取器类,它在循环中运行并查找消息。当我初始化阅读器时,它会创建一个连接和一个会话。然后,当有时间在循环中阅读消息时,它会创建MQQueue
和MQQueueReceiver
。这工作正常,我从队列中获取一个JMSMessage,然后将其交给另一个线程进行工作。如果工作线程失败,我想将该消息放回队列中(因此我的集群中的其他节点会重试该消息)。
我的问题是,我该如何回滚?我注意到rollback()
类中有一个MQQueueSession
方法。但我正在为我的所有消息重用相同的会话。我是否理解应该为每条消息创建一个新会话,而不是一遍又一遍地重复使用同一个会话?
这对我来说很直观。
此会话也是使用connection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
创建的。我应该使用CLIENT_ACKNOWLEDGE
以外的其他标志吗?
答案 0 :(得分:1)
您应该使用Session.SESSION_TRANSACTED标志和Session.commit / Sessiuon.rollback来提交/回滚当前事务中完成的所有消息
答案 1 :(得分:1)
请注意,JMS 1.1规范将会话定义为:
Session - 用于发送和接收消息的单线程上下文
后来在规范中说:
限制对Sessions的并发访问有两个原因。 首先,Sessions是支持事务的JMS实体。它是 很难实现多线程的事务。 其次,Sessions支持异步消息消费。它是 重要的是JMS不要求客户端代码用于异步 消息消费能够处理多个并发 消息。此外,如果已设置多个会话, 异步消费者,重要的是不要强制客户端 处理这些独立消费者同时发生的情况 执行。这些限制使JMS更易于使用 客户端。更复杂的客户端可以获得并发性 通过使用多个会话的愿望。
所以,不,你不需要每个消息一个会话。但是,会话期间生成或使用的所有消息都会一起提交或回滚,即使您已将它们移交给其他线程,此行为也符合规范。
使用Evgeniy所描述的事务会话和COMMIT / ROLLBACK,但也要注意将同一会话范围内的消息保存在同一工作单元内。