0

我有一个 JMS 2.0 MessageListener,即使消息已成功处理(通过日志确认),它似乎也会偶尔重新处理消息。我怀疑 session.commit() 需要完成,但我不确定,因为在绝大多数情况下,消息不会重试。据我了解,AUTO_ACKNOWLEDGE 是默认设置,但我不太确定它对 SessionAwareMessageListener 是如何工作的。

相关的 spring.xml 部分看起来像这样

<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        :
        :
        <property name="messageListener" ref="myMessageListener" />
        <property name="maxConcurrentConsumers" value="1" />
        <property name="receiveTimeout" value="5000" />
        <property name="sessionTransacted" value="true" />
    </bean>

MessageListener 实现如下

public class MyMessageListener implements SessionAwareMessageListener {

   // All spring autowired objects
   :
   :
   @Override
   public void onMessage(Message message, Session session)
   {
     logger.debug("JMSMessage ID : " + message.JMSMessageId, "Entering onMessage() ...");
     logger.debug("JMSMessage ID : " + message.JMSMessageId, "Retry Count : " + message.getIntProperty("JMSXDeliveryCount"));
     try
     {
     
     }
     catch(JMSException e)
     {
        // Log something 
        throw new RuntimeException(e);
     }
     catch(Exception ex)
     {
        if(certain types of exceptions)
        {
          session.rollback();
          System.Exit(1);
        }
        
        throw new RuntimeException(ex);

     }
     // THE FOLLOWING IS THE LAST LINE IN onMessage()
     logger.debug("JMSMessage ID : " + message.JMSMessageId,"Completed successfully !");

   }


}

所以,我现在看到的几乎所有消息都在日志​​中

:
JMSMessage Id : 1234, Entering onMessage()
JMSMessage Id : 1234, Retry count : 1
:
JmsMessage Id : 1234, Completed successfully!
JmsMessage Id : 3344, Entering onMessage() // New message taken up for processing.
JMSMessage Id : 3344, Retry count : 1

问题是偶尔(在数千条消息之后),我会在日志中看到这个

:
JMSMessage Id : 5566, Entering onMessage()
JMSMessage Id : 5566, Retry count : 1
:
JmsMessage Id : 5566, Completed successfully!
JMSMessage Id : 5566, Entering onMessage() // WHY IS JMS PROCESSING THE SAME MESSAGE (MESSAGEID : 5566) AGAIN ?
JMSMessage Id : 5566, Retry count : 2 
:
:
4

1 回答 1

1

当您sessionTransacted设置为 true 确认模式被忽略时,甚至可以设置一个特殊值来表示它没有被使用,从其他示例中我看到:

<property name="sessionAcknowledgeModeName" value="SESSION_TRANSACTED"/>

根据 Gary Russell 对 stackoverflow 问题Spring DMLC 消息消费的回答:auto_ack vs Transacted Session,如果您已sessionTransacted使用 DMLC 设置为 true ,则在调用侦听器后由 DMLC 提交会话,如果侦听器抛出异常则事务被回滚。

于 2020-08-17T08:15:26.983 回答