JMS Rollback&重新传递不遵守RedeliveryDelay配置

时间:2014-03-21 16:03:06

标签: spring apache-camel activemq

我想让我的Camel路由与ActiveMQ进行交易。回滚和最大重新交付工作正常,但不是重新传递延迟,这应该是递增的。

例如,当我无法处理消息(引发异常)时,它会重新传送3次(如预期的那样),但它之间的没有时间(不是)。

My Spring配置:

<context:annotation-config/>
<context:component-scan base-package="fr.dush.poc.springplaceholder"/>

<spring:camelContext>
    <spring:package>fr.dush.poc.springplaceholder.routes</spring:package>
    <spring:contextScan/>
</spring:camelContext>

<bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
    <property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>

<bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
    <property name="transactionManager" ref="jmsTransactionManager"/>
</bean>
<bean id="PROPAGATION_REQUIRES_NEW" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
    <property name="transactionManager" ref="jmsTransactionManager"/>
    <property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW"/>
</bean>

Spring配置在配置bean中继续:

@Component
public class CamelFactories {

private static final Logger LOGGER = LoggerFactory.getLogger(CamelFactories.class);

public static final int REDELIVERY_DELAY = 1000;
public static final int BACK_OFF_MULTIPLIER = 2;
public static final int HOUR = 3600000;
public static final int MAXIMUM_REDELIVERY_DELAY = 2 * HOUR;
public static final int MAXIMUM_REDELIVERIES = 3;

@Bean(name = "jmsConnectionFactory")
public ActiveMQConnectionFactory createFactory() {
    ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
    factory.setBrokerURL("tcp://localhost:61616");

    RedeliveryPolicy policy = new RedeliveryPolicy() {

        @Override
        public long getNextRedeliveryDelay(long previousDelay) {
            long nextDelay = super.getNextRedeliveryDelay(previousDelay);
            LOGGER.warn("Previous delay={} ; This delay={} ", previousDelay, nextDelay);
            return nextDelay;
        }
    };
    policy.setMaximumRedeliveries(MAXIMUM_REDELIVERIES);

    policy.setRedeliveryDelay(REDELIVERY_DELAY);
    policy.setBackOffMultiplier(BACK_OFF_MULTIPLIER);
    policy.setUseExponentialBackOff(true);
    policy.setMaximumRedeliveryDelay(MAXIMUM_REDELIVERY_DELAY);

    factory.setRedeliveryPolicy(policy);

    return factory;
}

@Bean(name = "activemq")
public JmsComponent createJmsComponent(JmsTransactionManager transactionManager,
        ActiveMQConnectionFactory connectionFactory) {

    ActiveMQComponent component = new ActiveMQComponent();
    component.setTransactionManager(transactionManager);
    component.setConnectionFactory(connectionFactory);
    component.setTransacted(true);

    return component;
}

我的路线非常简单:

public class CamelRouteBuilder extends SpringRouteBuilder {

  @Override
  public void configure() throws Exception {

    Policy required = getApplicationContext().getBean("PROPAGATION_REQUIRED",
            SpringTransactionPolicy.class);

    from("activemq:queue:foo.bar")
            .transacted()
            .policy(required)

            .log(LoggingLevel.INFO, "fr.dush.poc", "Receive message: ${body}")
            .beanRef("serviceBean") // throw an exception
            .to("mock:routeEnd");
  }
}

在我的日志中,我有这个,3次,之前的延迟= 0:

CamelFactories:36 - Previous delay=0 ; This delay=1000

似乎我并不是唯一一个遇到这个问题的人,但我仍然没有找到解决方案......

谢谢,

-Dush

2 个答案:

答案 0 :(得分:0)

我仍然没有找到解决方案。但我找到了另一种选择:从CAMEL本身重试API。

配置非常相似。 Spring配置示例:

<redeliveryPolicyProfile id="infiniteRedeliveryPolicy" 
                         asyncDelayedRedelivery="true"
                         redeliveryDelay="${camel.redelivery_delay}"
                         maximumRedeliveryDelay="${camel.maximum_redelivery_delay}"
                         maximumRedeliveries="${camel.infinite_redelivery}"
                         backOffMultiplier="${camel.back_off_multiplier}"
                         useExponentialBackOff="true"/>

<routeContext>
  <route>
    <!-- ... -->

    <!-- Define behaviour in case of technical error -->
    <onException redeliveryPolicyRef="infiniteRedeliveryPolicy">
       <exception>java.lang.Exception</exception>
       <handled>
           <constant>false</constant>
       </handled>

       <log message="Message can't be processed for now. I'll retry later!" />
    </onException>
  </route>
</routeContext>

如果您希望在ActiveMQ队列中保留未处理的消息,消费者应该事务性,即使您关闭了应用程序。

答案 1 :(得分:0)

这可以通过在ActiveMQComponent上设置cacheLevelName = CACHE_CONSUMER来解决。我有同样的症状和这解决了我。在相关的说明中,除非我使用CACHE_CONSUMER,否则我还会使用事务处理组件无法传递消息。