首页 > 解决方案 > Artemis - 如何避免非事务会话的 TransactionRolledBackException

问题描述

我将实时/备份与共享存储一起使用,并使用非事务 JMS 会话。我总是发送一条消息,我总是收到一条消息然后确认,只有在第一次确认成功后才收到第二条消息。

我在非交易会话中遇到了这个异常:

Execution of JMS message listener failed. Caused by: [javax.jms.TransactionRolledBackException - AMQ219030: The transaction was rolled back on failover to a backup server]
javax.jms.TransactionRolledBackException: AMQ219030: The transaction was rolled back on failover to a backup server
        at org.apache.activemq.artemis.core.client.impl.ClientSessionImpl.rollbackOnFailover(ClientSessionImpl.java:904)
        at org.apache.activemq.artemis.core.client.impl.ClientSessionImpl.commit(ClientSessionImpl.java:927)
        at org.apache.activemq.artemis.jms.client.ActiveMQMessage.acknowledge(ActiveMQMessage.java:719)

这是因为会话被标记为“ rollbackOnly ”。经过以下步骤后,我得到了这个状态:

  1. 我使用 Spring-JMS。消费者会话 24/7 工作(无限循环session.receive()
  2. 主节点崩溃,然后主节点重新启动
  3. 恢复后(几个小时后),我向队列发送了一条消息。消费者阅读消息并在确认时抛出异常(因为被标记为仅回滚)
  4. 我再次阅读了消息(这对我的任务来说不是很糟糕)但重新投递计数没有增加
  5. 我的消费者代码:
onMessage(Message message) {
  if (redeliveryCount(message) > 0){
    processAsDublicate(message);  // It's not invoked  - it is error in my business logic.
  }
}

  1. 我从另一个代理迁移,并且我认为不更改客户端逻辑

问题:

如何避免非事务性会话的 TransactionRolledBackException?如果这不可能,我应该更改消费者代码吗?

先感谢您

回答后更新

https://github.com/apache/activemq-artemis/tree/2.14.0/examples/features/ha/replicated-failback

这个例子不适合我的情况——我没有未确认的消息。经过以下步骤后,我得到了这个状态:1)重启服务器 2)消费消息 3)确认消息

  1. 我们为约 30 个应用程序 (24/7) 使用代理,总共约 200 个消费者
  2. 比如周末我们重启JMS Broker
  3. 所有消费者在消费新消息后是否都会开始收到此异常(他们没有未确认的消息)

标签: activemq-artemis

解决方案


如您在复制故障回复示例中所见,预期会出现 TransactionRolledBackException 。

为了防止消费者多次接收相同的消息,必须实现幂等消费者,即 Apache Camel 提供了可与任何 JMS 提供者一起使用的幂等消费者组件,请参阅:http ://camel.apache.org/idempotent-consumer .html


推荐阅读