应用程序服务器突然停止时,使用Spring JMS和ActiveMQ丢失JMS消息

时间:2016-12-21 04:02:49

标签: spring jms activemq spring-jms jmstemplate

我有一个Spring JMS应用程序,它有一个JMS Listener,可以在应用程序启动时连接到Active MQ队列。此JMS侦听器是应用程序的一部分,该应用程序接收消息,使用内容丰富消息,然后将其传递到同一ActiveMQ代理上的主题。

sessionTransacted设置为True。我没有执行任何数据库事务,因此我没有在任何地方设置@Transactional。根据我所读取的内容,sessionTransacted属性围绕JMS侦听器的接收方法设置本地事务,因此在事务完成之前它不会将消息从队列中拉出。我已经使用本地ActiveMQ实例和我的本地tomcat容器测试了它,并且它按预期工作。

但是,当我部署到PERF环境并重试相同的测试时,我注意到在服务器关闭时当前正在进行的消息在完成接收方法之前从队列中拉出。

我想知道的是,是否有任何明显的我应该寻找的东西?是否存在会导致此行为发生的某些JMS标头?如果我能提供更多信息,请告诉我。

我在运行Java 8的Tomcat 7容器上使用Spring 4.1.2.RELEASE和Apache ActiveMQ 5.8.0。

更新 - 添加我的Java JMS配置。请注意,为了清楚起见,我将PERF属性文件中的内容替换为相关区域。

    @Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() throws Throwable {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory());
    factory.setMaxMessagesPerTask(-1);
    factory.setConcurrency(1);
    factory.setSessionTransacted(Boolean.TRUE);
    return factory;
}

@Bean
public CachingConnectionFactory connectionFactory(){
    RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();

    redeliveryPolicy.setInitialRedeliveryDelay(1000);
    redeliveryPolicy.setRedeliveryDelay(1000);
    redeliveryPolicy.setMaximumRedeliveries(6);
    redeliveryPolicy.setUseExponentialBackOff(Boolean.TRUE);
    redeliveryPolicy.setBackOffMultiplier(5);

    ActiveMQConnectionFactory activeMQ = new ActiveMQConnectionFactory(environment.getProperty("queue.username"), environment.getProperty("queue.password"), environment.getProperty("jms.broker.endpoint"));
    activeMQ.setRedeliveryPolicy(redeliveryPolicy);
    activeMQ.setPrefetchPolicy(prefetchPolicy());

    CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(activeMQ);
    cachingConnectionFactory.setCacheConsumers(Boolean.FALSE);
    cachingConnectionFactory.setSessionCacheSize(1);
    return cachingConnectionFactory;
}

@Bean
public JmsMessagingTemplate jmsMessagingTemplate(){
    ActiveMQTopic activeMQ = new ActiveMQTopic(environment.getProperty("queue.out"));

    JmsMessagingTemplate jmsMessagingTemplate = new JmsMessagingTemplate(connectionFactory());
    jmsMessagingTemplate.setDefaultDestination(activeMQ);

    return jmsMessagingTemplate;
}

protected ActiveMQPrefetchPolicy prefetchPolicy(){
    ActiveMQPrefetchPolicy prefetchPolicy = new ActiveMQPrefetchPolicy();
    int prefetchValue = 0; 
    prefetchPolicy.setQueuePrefetch(prefetchValue);
    return prefetchPolicy;
}

谢谢,

1 个答案:

答案 0 :(得分:0)

事实证明,我们的PERF环境中部署了不同版本的应用程序。应用程序更新后,它按预期工作。