Apache Camel中的持久重试

时间:2017-07-20 11:57:17

标签: spring-boot apache-camel activemq

我正在努力使信息能够在Camel中保留重新传递信息:

from("activemq:incoming-queue")
     .errorHandler(
         deadLetterChannel("activemq:queue.dead-letter")
         .maximumRedeliveries(100)
         .redeliveryDelay(TimeUnit.SECONDS.toMillis(10))
     )
.to("http4://example.com")

如果发生故障,则会安排重试,如果我们关闭Camel,它会将消息放回ActiveMQ队列,这是好的。

问题是如果你用“kill -9”杀死它,那么消息将永远丢失,因为Camel在重试期间将它们保存在内存中。

问题是如何保证即使在系统突然中断的情况下,重试也不会丢失消息?

更新

我们使用交易实施了有保证的重新发送:

    @Bean
    public JmsTransactionManager jmsTransactionManager(ConnectionFactory connectionFactory) {
        JmsTransactionManager jmsTransactionManager = new JmsTransactionManager();
        jmsTransactionManager.setConnectionFactory(connectionFactory);

        return jmsTransactionManager;
    }

    /**
     * Disables ActiveMQ redelivery since it clashes with camel redelivery system
     */
    @Bean
    public RedeliveryPolicy redeliveryPolicy(ActiveMQConnectionFactory connectionFactory) {
        RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
        redeliveryPolicy.setMaximumRedeliveries(0);
        connectionFactory.setRedeliveryPolicy(redeliveryPolicy);
        return redeliveryPolicy;
    }

然后路由如下所示(注意transacted = true参数,由于某些原因.transacted()方法的行为不同):

from("activemq:incoming-queue?transacted=true")
         .errorHandler(
             deadLetterChannel("activemq:queue.dead-letter")
             .maximumRedeliveries(100)
             .redeliveryDelay(TimeUnit.SECONDS.toMillis(10))
         )
.to("http4://example.com")

使用这种方法有什么缺点吗?

2 个答案:

答案 0 :(得分:3)

让克劳斯的回答更加具体:

<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="${activemq.url}"/>
    <property name="userName" value="${activemq.userName}"/>
    <property name="password" value="${activemq.password}"/>
    <property name="redeliveryPolicy">
        <bean class="org.apache.activemq.RedeliveryPolicy">
            <property name="maximumRedeliveries" value="100"/>
            <property name="initialRedeliveryDelay" value="10000"/>
            <property name="redeliveryDelay" value="10000"/>
        </bean>
    </property>
</bean>

使用ActiveMQ重试100次,第一次重试等待10秒,然后每次重试等待10秒。

然后你可以省略Camel中的错误处理(从而将它留给ActiveMQ),但我会添加事务:

from("activemq:incoming-queue")
     .transacted("PROPAGATION_REQUIRED_JMS")
     .to("http4://example.com")

重试100次后,消息将以队列“ActiveMQ.DLQ”结束,除非你改变它。

答案 1 :(得分:2)

最好在ActiveMQ代理端配置这种持久重传,你可以这样做,因为它具有这样的功能。