兔子MQ死信交换未能正常工作,导致无限重试。

huangapple 未分类评论58阅读模式
标题翻译

Rabbitmq dead letter exchange not working resulting in infinite retries

问题

我得到一个生产者:

rabbitTemplate.convertAndSend(QueueConstants.PROVISIONING_EXCHANGE, QueueConstants.PROVISIONING_ROUTING_KEY, message);

我的配置:

@Bean
Queue organizationProvisioningQueue() {
    return QueueBuilder.durable(QueueConstants.PROVISIONING_QUEUE)
            .withArgument("x-dead-letter-exchange", "")
            .withArgument("x-dead-letter-routing-key", QueueConstants.DEAD_LETTER_QUEUE)
            .build();
}

@Bean
Queue deadLetterQueue() {
    return QueueBuilder.durable(QueueConstants.DEAD_LETTER_QUEUE).build();
}

@Bean
DirectExchange exchange() {
    return new DirectExchange(QueueConstants.PROVISIONING_EXCHANGE);
}

@Bean
Binding binding() {
    return BindingBuilder.bind(organizationProvisioningQueue()).to(exchange()).with(QueueConstants.PROVISIONING_ROUTING_KEY);
}

和我的消息处理器:

@RabbitListener(queues = QueueConstants.PROVISIONING_QUEUE)
public void process(ProvisioningMessage message) throws ProvisioningException {
    System.out.println("Processing " + message);

    throw new ProvisioningException ("Some ex " + message);
}

还有常量:

public static final String PROVISIONING_EXCHANGE = "provisioning-exchange";
public static final String PROVISIONING_ROUTING_KEY = "provisioning";
public static final String PROVISIONING_QUEUE = "provisioning-queue";
public static final String DEAD_LETTER_QUEUE = PROVISIONING_QUEUE + ".dlq";

死信队列无法正常工作,因为在抛出异常后每次都重新将消息放入队列,导致无限循环,而不是发送到死信队列。

我已经将队列名称更改为以 .dlq 结尾,因为有人建议这样做,但仍然没有成功。
我做错了什么?

英文翻译

I got a producer:

rabbitTemplate.convertAndSend(QueueConstants.PROVISIONING_EXCHANGE, QueueConstants.PROVISIONING_ROUTING_KEY, message);

And my config:

@Bean
Queue organizationProvisioningQueue() {
    return QueueBuilder.durable(QueueConstants.PROVISIONING_QUEUE)
            .withArgument("x-dead-letter-exchange", "")
            .withArgument("x-dead-letter-routing-key", QueueConstants.DEAD_LETTER_QUEUE)
            .build();
}

@Bean
Queue deadLetterQueue() {
    return QueueBuilder.durable(QueueConstants.DEAD_LETTER_QUEUE).build();
}

@Bean
DirectExchange exchange() {
    return new DirectExchange(QueueConstants.PROVISIONING_EXCHANGE);
}

@Bean
Binding binding() {
    return BindingBuilder.bind(organizationProvisioningQueue()).to(exchange()).with(QueueConstants.PROVISIONING_ROUTING_KEY);
}

and my message processor:

@RabbitListener(queues = QueueConstants.PROVISIONING_QUEUE)
public void process(ProvisioningMessage message) throws ProvisioningException {
    System.out.println("Processing " + message);

    throw new ProvisioningException ("Some ex " + message);
}

And the constants:

public static final String PROVISIONING_EXCHANGE = "provisioning-exchange";
public static final String PROVISIONING_ROUTING_KEY = "provisioning";
public static final String PROVISIONING_QUEUE = "provisioning-queue";

public static final String DEAD_LETTER_QUEUE = PROVISIONING_QUEUE + ".dlq";

The dead letter queue doesn't work as the message gets re-queued every time after the exception is thrown resulting in an infinite loop instead of going to the dead-letter-queue.

I've changed my queue name to end in .dlq as well since it was suggested but still no success.
What am I doing wrong?

答案1

得分: 0

你需要抛出 AmqpRejectAndDontRequeueException 异常,或者将监听容器的 defaultRequeueRejected 属性设置为 false

死信队列的名称无关紧要。

英文翻译

You need to either throw an AmqpRejectAndDontRequeueException or set the listener container's defaultRequeueRejected property to false.

The name of the dlq is irrelevant.

答案2

得分: 0

最近我遇到了类似的问题(在出现异常时消息无限重新排队)。在我这个情况下,设置这个应用程序属性解决了问题:

spring.rabbitmq.listener.simple.default-requeue-rejected=false
英文翻译

Recently I had similiar problem (infinite requeue of message in case of Exception). In my case setting up of this application property solved problem:

spring.rabbitmq.listener.simple.default-requeue-rejected=false

答案3

得分: 0

中文翻译如下:

在RabbitMQ中,从版本3.8.0开始提供了毒消息处理功能,通过使用新类型的队列:Quorum Queues。

Quorum队列支持处理毒消息,即导致消费者重复重新排队交付的消息(可能是由于消费者故障),以至于该消息从未被完全消费并得到积极确认,以便可以由RabbitMQ标记为删除。

请注意,Quorum队列当前不支持某些功能:

Quorum队列跟踪不成功的交付尝试次数,并在任何重新交付的消息中包含在“x-delivery-count”头中进行公开。

可以使用策略参数delivery-limit为队列设置交付限制。当消息返回的次数超过限制时,该消息将被丢弃或进入死信队列(如果配置了DLX)。

兔子MQ死信交换未能正常工作,导致无限重试。

英文翻译

Poison message handling in RabbitMQ it is available as of RabbitMQ 3.8.0, by using the new type of queue: Quorum Queues.

兔子MQ死信交换未能正常工作,导致无限重试。

Quorum queue support handling of poison messages, that is, messages that cause a consumer to repeatedly requeue a delivery (possibly due to a consumer failure) such that the message is never consumed completely and positively acknowledged so that it can be marked for deletion by RabbitMQ.

Be aware, some features are not currently supported by quorum queues:

兔子MQ死信交换未能正常工作,导致无限重试。

Quorum queues keep track of the number of unsuccessful delivery attempts and expose it in the "x-delivery-count" header that is included with any redelivered message.

It is possible to set a delivery limit for a queue using a policy argument, delivery-limit. When a message has been returned more times than the limit the message will be dropped or dead-lettered (if a DLX is configured).

兔子MQ死信交换未能正常工作,导致无限重试。

huangapple
  • 本文由 发表于 2020年3月16日 17:53:58
  • 转载请务必保留本文链接:https://java.coder-hub.com/60703733.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定