【问题标题】:Spring JMS listener acknowledging even when exception即使出现异常,Spring JMS 侦听器也会确认
【发布时间】:2017-05-08 21:04:56
【问题描述】:

我正在使用 JMS 向我的 SQS 队列发送/接收消息,但是即使在使用 client_acknowledge 时出现异常,我也无法重新传递消息。如何做到这一点? 我尝试了一个简单的测试,

@JmsListener(destination = "test-normalqueue")
public void receiveNormalQueue(String message)
{

    try {
        logger.info("message received in normal queue: " + message);
        throw new NullPointerException();

    } catch (Exception e) {

        logger.error(LoggingUtil.getStackTrace(e));;
    }

}

即使异常消息没有返回队列。

@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(getSQSConnectionFactory());
    factory.setConcurrency("1-2");
    factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
    return factory;
}

【问题讨论】:

  • 也不例外。你正在捕捉一切。 Spring 需要看到一个异常来回滚/不承认它,但是当你捕捉它(并吞下)Spring 认为一切都很好。
  • 您好,感谢您的澄清。但是我对这种方法有一个疑问,如果我抛出异常,消息将重新排队,但是监听器会再次将其拉回并再次抛出异常形成循环,我该如何处理这种情况?
  • 这是您想在代理处处理的事情(我对 SQS 选项不太熟悉),但通常您可以配置多次重新传递消息,然后丢弃或移动到不同的频道/队列。
  • 感谢您的解释,我刚刚查了一下,发现 SQS 中的 DLQ 是出于完全相同的目的。

标签: java amazon-web-services spring-boot amazon-sqs spring-jms


【解决方案1】:

您必须使用 DMLC 的交易。

使用Session.AUTO_ACKNOWLEDGEsetSessionTransacted(true)

如果监听器正常退出,则消息被移除。如果侦听器抛出异常,则消息将回滚到队列中。

您也可以对事务使用客户端模式,但您必须自己确认成功的消息。

您不必使用带有SimpleMessageListenerContainer 的事务,但您仍然必须抛出异常才能使消息重新排队。

【讨论】:

【解决方案2】:

只有当侦听器停止并与代理断开连接时,消息才会返回队列,您所描述的行为是在 DefaultMessageListenerContainer 的客户端上,它将消息发送到您的侦听器并管理异常和重试,代理不知道在这些处理中,他只知道这些消息已发送给客户端并正在等待确认。 如果在 MessageConsumer 的实现上存在重置或重启等方法,则取决于 SQS 方法和功能。 您可以尝试 jms 会话的恢复()方法,但我认为这只会在客户端重新启动交付。 https://docs.oracle.com/javaee/7/api/javax/jms/Session.html#recover--

这是一个不好的做法,但是如果您重新启动连接或 DefaultMessageListenerContainer,未确认的消息会返回到代理并重新启动传递。

【讨论】:

  • 我不太明白,这里的broker是什么?你想让我怎么解决这个问题?无论如何,我们可以用 jmslistener 做到吗?
  • 这里的代理是 SQS,因为它公开了一个 JMS 接口。 JMS的原理是客户端必须处理消息,你能解释一下为什么你想让消息回到队列中
  • 您说 ** 当出现异常时,我无法重新传递消息** 因为您正在捕获异常,如果您想要要重新传递给监听器的消息,您必须在记录后抛出异常
  • 您好,感谢您的澄清。但是我对这种方法有一个疑问,如果我抛出异常,消息将重新排队,但是监听器会再次将其拉回并再次抛出异常形成循环,我该如何处理这种情况?
猜你喜欢
  • 2023-03-26
  • 2015-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-07
  • 1970-01-01
  • 1970-01-01
  • 2018-10-05
相关资源
最近更新 更多