JMS侦听器中有关异常的JMS消息重新交付 [英] JMS message redelivery on exception in JMS listener

查看:281
本文介绍了JMS侦听器中有关异常的JMS消息重新交付的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

用于org.springframework.jms.listener.AbstractMessageListenerContainer的Javadoc指出,如果

Javadoc for org.springframework.jms.listener.AbstractMessageListenerContainer states, that if

将"sessionAcknowledgeMode"设置为"CLIENT_ACKNOWLEDGE":成功执行侦听器后自动进行消息确认;如果发生异常,则不进行重新交付.

"sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE": Automatic message acknowledgment after successful listener execution; no redelivery in case of exception thrown.

我猜想,如果抛出异常,则不会重新交付"的意思是,即使在jms侦听器中抛出了异常,也不会重新传递该消息(所以,我的猜测,这将得到确认).但是,好吧,从侦听器抛出的异常意味着对它的调用未成功,并且由于没有确认而应该重新交付.

I guess, "no redelivery in case of exception thrown" means, that message would not be redelivered (so, my guess, it would be acknowledged), even if there's an exception thrown in the jms listener. But, well, exception thrown from listener means that call to it wasn't successful, and there should be redelivery due to no acknowledgement.

问题是:
在jms侦听器中引发异常的情况下,消息确认实际上应如何处理?

实际上会发生什么,可以从此堆栈跟踪中看到:

What really happens, might be seen from this stacktrace:

at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:98)
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:66)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:660)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:620)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:591)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:308)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:246)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1142)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1134)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1031)

stacktrace的第5行特别令人关注.那里的代码基本上意味着,(大部分)从侦听器引发的任何异常都将绕过在org.springframework.jms.listener.AbstractMessageListenerContainer#commitIfNecessary中完成的确认.
可以,但是"在抛出异常的情况下不交还"是什么意思?

Line 5 of the stacktrace is of particular interest. Code there basically means, that (mostly) whatever exception thrown from the listener will bypass the ackowledgement which is done in org.springframework.jms.listener.AbstractMessageListenerContainer#commitIfNecessary.
That's ok, but what does "no redelivery in case of exception thrown" mean then?

其他信息:
spring-jms:4.1.2

Additional info:
spring-jms:4.1.2

<bean id="someListenerContainerFactory" class="org.springframework.jms.config.DefaultJmsListenerContainerFactory">
    <property name="connectionFactory" ref="connectionFactory"/>
    <property name="concurrency" value="1-10"/>
    <property name="sessionAcknowledgeMode">
        <util:constant static-field="javax.jms.Session.CLIENT_ACKNOWLEDGE"/>
    </property>
</bean>

推荐答案

这取决于您使用的侦听器容器.当使用AUTO ACK模式时,SimpleMessageListenerContainer会在侦听器返回后进行确认(即传统的JMS MessageListener). DefaultMessageListenerContainer在调用侦听器之前先确认,因此您需要acknowledgeMode="transacted"来防止消息丢失.

It depends on which listener container you use; when using AUTO ack mode, the SimpleMessageListenerContainer acks after the listener returns (i.e. a traditional JMS MessageListener). The DefaultMessageListenerContainer acks before the listener is invoked, so you need acknowledgeMode="transacted" to prevent message loss.

这方面的javadocs有点误导,并且最近有所改善.

The javadocs in this area were a bit misleading and have been improved recently.

使用CLIENT_ACKNOWLEDGE,您可以自己完成任务.该文档仅表示您对经纪人一时的兴致.根据JMS消息javadoc:

With CLIENT_ACKNOWLEDGE, you're on your own to do the acks. That doc just means you are at the whim of the broker. According to the JMS message javadoc:

已收到但未确认的邮件可能会重新发送

Messages that have been received but not acknowledged may be redelivered

根据我的经验,最好对SMLC使用自动确认,对DMLC使用事务.

In my experience it is best to use auto ack with an SMLC and transactions with DMLC.

这篇关于JMS侦听器中有关异常的JMS消息重新交付的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆