简体   繁体   English

spring amqp死信队列不适用于事务

[英]spring amqp dead letter queue does not work with transaction

How can I setup listener container when is channelTransacted(true) to throw message into dead letter queue when is something wrong instead of requeue? 当出现问题而不是重新排队时,如何在channelTransacted(true)将消息放入死信队列时设置侦听器容器? When I do not use channelTransacted, everything works fine and I can see the message in the dead letter queue. 当我不使用channelTransacted时,一切正常,我可以在死信队列中看到该消息。

@Bean(name = "amqpInboundEsignRequest")
public IntegrationFlow amqpInbound(ConnectionFactory connectionFactory, PlatformTransactionManager transactionManager) {
    return IntegrationFlows.from(
            Amqp.inboundAdapter(connectionFactory, esignIAutoRequestQueue())
                    .acknowledgeMode(AcknowledgeMode.AUTO)
                    .messageConverter(new Jackson2JsonMessageConverter())
                    .autoStartup(false)
                    .defaultRequeueRejected(false)
                    //.channelTransacted(true) // dead letter does not work
                    //.transactionManager(transactionManager) // dead letter does not work
    )
            .log("amqpInbound.start-process")
            .handle(p -> {
                throw new RuntimeException("Something wrong!");
            })
            .get();
}

EDIT 编辑

These are versions of dependencies. 这些是依赖项的版本。

[INFO] +- org.springframework.boot:spring-boot-starter-amqp:jar:1.5.9.RELEASE:compile
[INFO] |  +- org.springframework:spring-messaging:jar:4.3.13.RELEASE:compile
[INFO] |  \- org.springframework.amqp:spring-rabbit:jar:1.7.4.RELEASE:compile
[INFO] |     +- com.rabbitmq:http-client:jar:1.1.1.RELEASE:compile
[INFO] |     +- com.rabbitmq:amqp-client:jar:4.0.3:compile
[INFO] |     +- org.springframework.retry:spring-retry:jar:1.2.1.RELEASE:compile
[INFO] |     \- org.springframework.amqp:spring-amqp:jar:1.7.4.RELEASE:compile

[INFO] +- org.springframework.boot:spring-boot-starter-integration:jar:1.5.9.RELEASE:compile
[INFO] |  +- org.springframework.integration:spring-integration-core:jar:4.3.12.RELEASE:compile
[INFO] |  \- org.springframework.integration:spring-integration-java-dsl:jar:1.2.3.RELEASE:compile
[INFO] |     \- org.reactivestreams:reactive-streams:jar:1.0.0:compile

I would like to have transaction synchronized with the external transaction db (PlatformTransactionManager). 我想使事务与外部事务数据库(PlatformTransactionManager)同步。 When I set transactionManager(transactionManager) on listener container it always do requeue. 当我在侦听器容器上设置transactionManager(transactionManager)时,它总是会重新排队。

What version are you using? 您使用什么版本? I just tested channelTransacted=true with Spring Integration 5.0.2 and Spring AMQP 2.0.2, as well as Spring Integration 4.3.14 and Spring AMQP 1.7.6 and everything works as expected, the failed message went to the DLQ. 我刚刚使用Spring Integration 5.0.2和Spring AMQP 2.0.2以及Spring Integration 4.3.14和Spring AMQP 1.7.6测试了channelTransacted=true ,并且一切正常,失败的消息发送到了DLQ。

@SpringBootApplication
public class So48914749Application {

    public static void main(String[] args) {
        SpringApplication.run(So48914749Application.class, args);
    }

    @Bean
    public IntegrationFlow amqpInbound(ConnectionFactory connectionFactory) {
        return IntegrationFlows.from(
                Amqp.inboundAdapter(connectionFactory, "foo")
                        .acknowledgeMode(AcknowledgeMode.AUTO)
                        .messageConverter(new Jackson2JsonMessageConverter())
                        .autoStartup(true)
                        .defaultRequeueRejected(false)
                        .channelTransacted(true) // dead letter does not work
        // .transactionManager(transactionManager) // dead letter does not work
        )
                .log("amqpInbound.start-process")
                .handle(p -> {
                    throw new RuntimeException("Something wrong!");
                })
                .get();
    }

    @Bean
    public Queue queue() {
        return QueueBuilder.durable("foo")
                .withArgument("x-dead-letter-exchange", "")
                .withArgument("x-dead-letter-routing-key", "dlq")
                .build();
    }

    @Bean
    public Queue dlq() {
        return new Queue("dlq");
    }

    @RabbitListener(queues = "dlq")
    public void dlq(Message in) {
        System.out.println(in);
    }

}

result: 结果:

(Body:'[B@17793549(byte[8])' MessageProperties [headers={x-first-death-exchange=, x-death=[{reason=rejected, count=1, exchange=, time=Wed Feb 21 16:43:48 EST 2018, routing-keys=[foo], queue=foo}], x-first-death-reason=rejected, x-first-death-queue=foo}, timestamp=null, messageId=null, userId=null, receivedUserId=null, appId=null, clusterId=null, type=null, correlationId=null, correlationIdString=null, replyTo=null, contentType=null, contentEncoding=null, contentLength=0, deliveryMode=null, receivedDeliveryMode=NON_PERSISTENT, expiration=null, priority=null, redelivered=false, receivedExchange=, receivedRoutingKey=dlq, receivedDelay=null, deliveryTag=4, messageCount=0, consumerTag=amq.ctag-dOypXDkkQ5Hvw2W9cUIpzg, consumerQueue=dlq]) (正文:“ [B @ 17793549(byte [8])”)MessageProperties [headers = {x-first-death-exchange =,x-death = [{原因=已拒绝,count = 1,交换=,时间= 2月周三21:43:48 EST 2018,路由键= [foo],队列= foo}],x-first-death-reason =已拒绝,x-first-death-queue = foo},时间戳= null,messageId = null,userId = null,receivedUserId = null,appId = null,clusterId = null,type = null,correlationId = null,correlationIdString = null,replyTo = null,contentType = null,contentEncoding = null,contentLength = 0,deliveryMode = null, receiveedDeliveryMode = NON_PERSISTENT,到期时间为null,优先级为null,重新交付的结果为false,receivedExchange =,receivedRoutingKey = dlq,receivedDelay = null,deliveryTag = 4,messageCount = 0,consumerTag = amq.ctag-dOypXDkkQ5Hvw2W9cUIpzg,consumerQueue = dlq)

EDIT 编辑

Please be more precise in future; 将来请更精确; your question implied the same problem occurred regardless of whether a transaction manager was provided. 您的问题暗示无论是否提供了事务管理器,都会发生相同的问题。

See the second NOTE under A note on Rollback of Received Messages . 请参阅回滚收到的邮件的注释”下的第二个注释 This is fixed in 2.0. 这在2.0中已修复。

In 1.7.x, we had to retain the old behavior by default, for backwards compatibility. 在1.7.x中,为了向后兼容,我们必须默认保留旧的行为。 The 1.7.x documentation explains that you have to set the alwaysRequeueWithTxManagerRollback to false the get the new (consistent) behavior. 1.7.x文档说明您必须将alwaysRequeueWithTxManagerRollback设置为false才能获得新的(一致的)行为。

This is a listener container property so you will need to wire up a container and inject it into the inbound channel adapter. 这是一个侦听器容器属性,因此您需要连接一个容器并将其注入入站通道适配器。

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

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