如果队列不存在,则消息丢失

Posted

技术标签:

【中文标题】如果队列不存在,则消息丢失【英文标题】:Messages lost if queue does not exist 【发布时间】:2017-10-25 20:04:05 【问题描述】:

当我们向 RabbitMQ 发送消息时,如果队列不存在,则消息会丢失而不会引发任何错误。

邮件将发布到哪里?死队列?

【问题讨论】:

【参考方案1】:

这就是 RabbitMQ 的设计方式 - 发布者发布到交易所,而不是队列。

如果没有队列绑定(如果交换需要,则使用匹配的路由键),则简单地丢弃该消息。

您可以enable publisher returns 并在发布时设置mandatory 标志,代理将返回消息(但它到达不同的线程,而不是发布线程)。

【讨论】:

【参考方案2】:

您的消息可以退回给您

如果没有绑定到交换的队列。要接收它们并且不丢失这些消息,您必须执行以下操作:

1。将这些属性添加到您的 application.yml

spring:
  rabbitmq:
    publisher-confirm-type: correlated
    publisher-returns: true
    template:
      mandatory: true

2。创建 RabbitConfirmCallback

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;

@Component
public class RabbitConfirmCallback implements RabbitTemplate.ConfirmCallback 
    private static final Logger logger = LoggerFactory.getLogger(RabbitConfirmCallback.class);

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) 
        if (ack && correlationData != null && correlationData.getId() != null) 

            Message returnedMessage = correlationData.getReturnedMessage();
            String dataId = correlationData.getId();

            if (returnedMessage != null) 
                logger.error("Message wasn't delivered to Consumer; " + returnedMessage + "\nCorrelationData id = " + dataId);
             else 
                logger.info("CorrelationData with id " + dataId + " acknowledged;");
            

         else 
            if (ack) 
                logger.warn("Unknown message acknowledgement received: " + correlationData);
             else 
                logger.info("Broker didn't accept message: " + cause);
            
        
    

这个回调方法confirm(...)将被触发,在这种无限制队列的交换中尝试发送消息之后。 在correlationData 对象中,您会发现returnedMessage 字段将是您的消息的messagePropertiesbody

3。将 RabbitConfirmCallback 设置为 RabbitTemplate

@Autowired
public void post(RabbitTemplate rabbitTemplate, RabbitConfirmCallback rabbitConfirmCallback)
    rabbitTemplate.setConfirmCallback(rabbitConfirmCallback);

4。发送消息时,添加 CorrelationDate 对象

带有一些唯一标识符

rabbitTemplate.convertAndSend(exchange, routingKey, wrapMessage(message),
                              new CorrelationData(stringId));

【讨论】:

以上是关于如果队列不存在,则消息丢失的主要内容,如果未能解决你的问题,请参考以下文章

RabbitMQ消息队列怎样做到服务宕机或重启消息不丢失

MQ在高并发环境下,如果队列满了,如何防止消息丢失?

消息队列:可靠性重复消息消息积压分布式事务

RabbitMQ面试题:如何确保消息不丢失? --- 2022-04-03

一文弄懂消息队列相关面试问题:消息可靠性重复消息消息积压利用消息实现分布式事务

消息队列漫谈:消息丢失,消息重复,消息积压一些处理方式