简体   繁体   English

未设置ActiveMQ RedeliveryPolicy

[英]ActiveMQ RedeliveryPolicy not being set

I´m using: 我正在使用:

  • SpringBoot 2.0.4 SpringBoot 2.0.4
  • ActiveMQ 5.15.5 ActiveMQ 5.15.5
  • Apache Camel 2.22.0 阿帕奇骆驼2.22.0
  • Java 1.8 Java 1.8
  • Groovy Groovy的
  • Maven Maven的

Basically, I have a SpringBoot application with an Apache Camel route which consumes messages from ActiveMQ with transactions. 基本上,我有一个带有Apache Camel路由的SpringBoot应用程序,该路由使用ActiveMQ的消息进行事务处理。 I need to set a RedeliveryPolicy on ActiveMQ, so when an error in processing happens, the message is retried a number of times. 我需要在ActiveMQ上设置RedeliveryPolicy,因此当处理中发生错误时,将重试该消息多次。

I have made a configuration class with beans for ActiveMQ, the transactions work as intended but the RedeliveryPolicy does not work. 我使用ActiveMQ的bean创建了一个配置类,事务按预期工作,但是RedeliveryPolicy无法工作。 Can anybody please help me understand what's wrong with this? 有人可以帮我了解这是怎么回事吗?

Here's the log output for a message that produces an error: 这是产生错误的消息的日志输出:

2018-10-23 10:35:28.005 DEBUG 10524 --- [mer[entryQueue]] oacsspi.TransactionErrorHandler : Transaction begin (0x35d60381) redelivered(false) for (MessageId: ID:EPIC-LAP-25-50304-1540306817804-4:3:1:1:2 on ExchangeId: ID-EPIC-LAP-25-1540312510586-0-1)) 2018-10-23 10:35:28.020 DEBUG 10524 --- [mer[entryQueue]] o.apache.camel.processor.SendProcessor : >>>> direct://middle Exchange[ID-EPIC-LAP-25-1540312510586-0-1] 2018-10-23 10:35:28.375 DEBUG 10524 --- [mer[entryQueue]] oacamel.processor.DefaultErrorHandler : Failed delivery for (MessageId: ID:EPIC-LAP-25-50304-1540306817804-4:3:1:1:2 on ExchangeId: ID-EPIC-LAP-25-1540312510586-0-1). 2018-10-23 10:35:28.005调试10524 --- [mer [entryQueue]] oacsspi.TransactionErrorHandler:为(MessageId:ID:EPIC-LAP-25-50304-1540306817804-)重新传输(false)事务开始(0x35d60381) ExchangeId上的4:3:1:1:2:ID-EPIC-LAP-25-1540312510586-0-1))2018-10-23 10:35:28.020 DEBUG 10524 --- [mer [entryQueue]] o。 apache.camel.processor.SendProcessor:>>>>直接://中间交易平台[ID-EPIC-LAP-25-1540312510586-0-1] 2018-10-23 10:35:28.375 DEBUG 10524 --- [mer [entryQueue] oacamel.processor.DefaultErrorHandler:在(ExchangeId:ID-EPIC-LAP-25-1540312510586-(MessageId:ID:EPIC-LAP-25-50304-1540306817804-4:3:1:1:2)上传递失败0-1)。 On delivery attempt: 0 caught: java.lang.RuntimeException: ExceptionTest: Order Failed 2018-10-23 10:35:28.390 ERROR 10524 --- [mer[entryQueue]] oacamel.processor.DefaultErrorHandler : Failed delivery for (MessageId: ID:EPIC-LAP-25-50304-1540306817804-4:3:1:1:2 on ExchangeId: ID-EPIC-LAP-25-1540312510586-0-1). 交付尝试:0捕获:java.lang.RuntimeException:ExceptionTest:订单失败2018-10-23 10:35:28.390错误10524 --- [mer [entryQueue]] oacamel.processor.DefaultErrorHandler:(MessageId:在ExchangeId上ID:EPIC-LAP-25-50304-1540306817804-4:3:1:1:2:ID-EPIC-LAP-25-1540312510586-0-1)。 Exhausted after delivery attempt: 1 caught: java.lang.RuntimeException: ExceptionTest: Order Failed 尝试交付后已用尽:1个被捕获:java.lang.RuntimeException:ExceptionTest:订单失败

Here's my config class for ActiveMQ: 这是我的ActiveMQ配置类:

import org.apache.activemq.ActiveMQConnectionFactory
import org.apache.activemq.RedeliveryPolicy
import org.apache.activemq.camel.component.ActiveMQComponent
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.jms.connection.JmsTransactionManager

import javax.jms.DeliveryMode

@Configuration
class ActiveMQConfiguration {

    @Bean
    ActiveMQConnectionFactory activeMQConnectionFactory() {
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory()
        activeMQConnectionFactory.brokerURL = 'tcp://localhost:61616'
        activeMQConnectionFactory.userName = 'admin'
        activeMQConnectionFactory.password = 'admin'

        RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy()
        redeliveryPolicy.maximumRedeliveries = 3
        redeliveryPolicy.redeliveryDelay = 150L
        redeliveryPolicy.useExponentialBackOff = true
        redeliveryPolicy.backOffMultiplier = 1.5

        activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy)

        activeMQConnectionFactory
    }

    @Bean
    ActiveMQComponent activeMQComponent(@Qualifier('activeMQConnectionFactory')ActiveMQConnectionFactory activeMQConnectionFactory) {
        ActiveMQComponent activeMQComponent = new ActiveMQComponent()
        activeMQComponent.connectionFactory = activeMQConnectionFactory
        activeMQComponent.transacted = true
        activeMQComponent.transactionManager = txManager()
        activeMQComponent.cacheLevelName = 'CACHE_CONSUMER'
        activeMQComponent.lazyCreateTransactionManager = false
        activeMQComponent.deliveryMode = DeliveryMode.PERSISTENT

        activeMQComponent
    }

    @Bean
    JmsTransactionManager txManager(@Qualifier('activeMQConnectionFactory') ActiveMQConnectionFactory activeMQConnectionFactory) {
        JmsTransactionManager txManager = new JmsTransactionManager()
        txManager.connectionFactory = activeMQConnectionFactory
        txManager.rollbackOnCommitFailure = true

        txManager
    }

}

Not very long ago I had problems with dlq queues - not all parameters set in the code worked. 不久前,我遇到了dlq队列的问题-并非代码中设置的所有参数都能正常工作。 I had to add settings to acitvemq configs. 我必须将设置添加到acitvemq配置。 Yes, it is not a good decision to divide configs but I didn't find another. 是的,划分配置不是一个好的决定,但我没有找到其他配置。 Below is my config class for jms and an example queue configuration via activemq.xml: 以下是我的jms配置类和通过activemq.xml进行示例队列配置:

@Configuration
@EnableJms
public class JmsConfig {

    private Environment env;

    @Autowired
    public void setEnv(Environment env) {
        this.env = env;
    }

    @Bean(name = "activemq")
    public ActiveMQComponent activemq(@Qualifier("activemqTransactionManager") JmsTransactionManager jmsTransactionManager,
                                      @Qualifier("activemqConnectionFactory") ConnectionFactory connectionFactory) {
        ActiveMQComponent activeMQComponent = new ActiveMQComponent();
        activeMQComponent.setTransactionManager(jmsTransactionManager);
        activeMQComponent.setConnectionFactory(connectionFactory);
        return activeMQComponent;
    }

    @Bean(name = "activemqJmsTemplate")
    public JmsTemplate jmsTemplate(@Qualifier("activemqConnectionFactory") ConnectionFactory connectionFactory) {
        JmsTemplate template = new JmsTemplate();
        template.setConnectionFactory(connectionFactory);
        return template;
    }

    @Bean(name = "activemqTransactionPolicy")
    public SpringTransactionPolicy activemqTransactionPolicy(
            @Qualifier("activemqTransactionManager") JmsTransactionManager jmsTransactionManager) {
        SpringTransactionPolicy springTransactionPolicy = new SpringTransactionPolicy(jmsTransactionManager);
        springTransactionPolicy.setPropagationBehaviorName("PROPAGATION_REQUIRED");
        return springTransactionPolicy;
    }

    @Bean(name = "activemqTransactionManager")
    public JmsTransactionManager activemqTransactionManager(
            @Qualifier("activemqConnectionFactory") ConnectionFactory connectionFactory) {
        return new JmsTransactionManager(connectionFactory);
    }

    @Bean(name = "activemqConnectionFactory")
    public ConnectionFactory connectionFactory(@Qualifier("activemqRedeliveryPolicy") RedeliveryPolicy redeliveryPolicy) {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
        connectionFactory.setBrokerURL("tcp://" + env.getProperty("queue.url"));
        connectionFactory.setTrustAllPackages(true);

        RedeliveryPolicyMap map = connectionFactory.getRedeliveryPolicyMap();
        map.put(new ActiveMQQueue("queueName.DLQ"), redeliveryPolicy);
        return connectionFactory;
    }

    @Bean(name = "activemqRedeliveryPolicy")
    public RedeliveryPolicy redeliveryPolicy() {
        RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
        redeliveryPolicy.setMaximumRedeliveries(0);
        return redeliveryPolicy;
    }
}

Changes in activevq.xml: activevq.xml中的更改:

<destinationPolicy>
    <policyMap>
        <policyEntries>
            <!--set dead letter queue for our queue. It name will be "myQueueName.DLQ"-->
            <policyEntry queue="myQueueName">
                <deadLetterStrategy>
                    <individualDeadLetterStrategy queuePrefix="" queueSuffix=".DLQ"/>
                </deadLetterStrategy>
            </policyEntry>
            <policyEntry topic=">">
                <pendingMessageLimitStrategy>
                    <constantPendingMessageLimitStrategy limit="1000"/>
                </pendingMessageLimitStrategy>
            </policyEntry>
        </policyEntries>
    </policyMap>
</destinationPolicy>

<plugins>
<redeliveryPlugin fallbackToDeadLetter="true" sendToDlqIfMaxRetriesExceeded="true">
    <redeliveryPolicyMap>
        <redeliveryPolicyMap>
            <redeliveryPolicyEntries>
                <!--Set the redelivery delay to one hour-->
                <redeliveryPolicy queue="myQueueName.DLQ" maximumRedeliveries="-1" redeliveryDelay="3600000"/>
            </redeliveryPolicyEntries>
        </redeliveryPolicyMap>
    </redeliveryPolicyMap>
</redeliveryPlugin>
</plugins>

There are two issues here 这里有两个问题

1. You have two transaction managers 1.您有两个交易经理

Due to the following two lines in your configuration of the Camel ActiveMQ component, you configure two transaction managers. 由于在配置骆驼ActiveMQ组件时需要执行以下两行,因此需要配置两个事务管理器。 That is a source of problems. 那是问题的根源。

activeMQComponent.transacted = true // activates local JMS transactions
activeMQComponent.transactionManager = txManager() // additional tx manager

if you just want to consume transactional from ActiveMQ, you don't need to configure a Spring transaction manager . 如果您只想使用ActiveMQ的事务性, 则不需要配置Spring事务管理器

These two lines of your config are enough to get local transactions with your ActiveMQ broker. 配置的这两行足以与ActiveMQ代理进行本地事务。

activeMQComponent.transacted = true
activeMQComponent.lazyCreateTransactionManager = false

So you should remove this line as well as the whole txManager bean 因此,您应该删除此行以及整个txManager bean

activeMQComponent.transactionManager = txManager()

If you currently set the transacted flag in your Camel routes, you have to remove this too. 如果您当前在骆驼路线中设置了交易标记,则也必须将其删除。 And as I wrote, your routes consuming from ActiveMQ are still transacted even if you remove all this. 正如我所写,即使删除了所有这些,从ActiveMQ消耗的路由仍会被处理。

2. Redelivery not working 2.重新交付不起作用

You have not published your Camel routes, but according to the error output, I assume that the broker does not redeliver because the error is handled by Camel . 您尚未发布您的Camel路线,但是根据错误输出,我认为代理未重新交付,因为错误是由Camel处理的

It is the Camel error handler oacamel.processor.DefaultErrorHandler that kicks in when the error occurs and because it handles the error, the message is commited against the broker and therefore no redelivery takes place. 发生错误时将启动Camel错误处理程序oacamel.processor.DefaultErrorHandler ,并且由于它处理错误,因此将消息提交给代理,因此不会进行重新交付。

Try to disable Camel error handling to see if the broker redelivers messages on errors. 尝试禁用骆驼错误处理,以查看代理是否重新发送错误消息。

errorHandler(noErrorHandler());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM