JMS 侦听器中出现异常时重新传递 JMS 消息

问题描述 投票:0回答:2

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

“sessionAcknowledgeMode”设置为“CLIENT_ACKNOWLEDGE”:监听器执行成功后自动消息确认;抛出异常时不会重新投递。

我想,“抛出异常时不重新传递”意味着,即使 jms 监听器中抛出异常,该消息也不会被重新传递(所以,我猜,它会被确认)。但是,监听器抛出的异常意味着对它的调用不成功,并且由于没有确认而应该重新传递。

问题是:
如果 jms 监听器中抛出异常,消息确认实际上应该发生什么?

真正发生的事情,可以从这个堆栈跟踪中看到:

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)

堆栈跟踪的第 5 行特别令人感兴趣。那里的代码基本上意味着,(大多数)从侦听器抛出的任何异常都将绕过

org.springframework.jms.listener.AbstractMessageListenerContainer#commitIfNecessary
中完成的确认。
没关系,但是“抛出异常时不重新投递”是什么意思呢?

附加信息:
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>
java spring spring-jms
2个回答
4
投票

这取决于你使用哪个监听器容器;当使用 AUTO ack 模式时,

SimpleMessageListenerContainer
在侦听器返回后进行确认(即传统的 JMS
MessageListener
)。
DefaultMessageListenerContainer
在调用侦听器之前进行确认,因此您需要
acknowledgeMode="transacted"
来防止消息丢失。

该领域的 javadoc 有点误导性,并且最近已得到改进

使用 CLIENT_ACKNOWLEDGE,您可以自己进行确认。那个文件只是意味着你听从经纪人的突发奇想。根据JMS消息javadoc:

已收到但未确认的消息可以重新发送

根据我的经验,最好使用带有

SMLC
的自动确认和带有
DMLC
的交易。


0
投票

根据我的经验,最好将自动确认与 SMLC 结合使用,将交易与 DMLC 结合使用。 这对我在 Weblogic 中使用 JMS 实现有很大帮助

© www.soinside.com 2019 - 2024. All rights reserved.