springboot rabbitmq對消費者和生產者丟消息設置

 

首先講解防止生產者丟失信息處理。

1、設置發送消息確認: publisher-confirms: true

2、啓動消息失敗返回: publisher-returns: true

在yml中配置如下

spring:

rabbitmq:
  host: localhost
  port: 5672
  virtual-host: mall
  username: guest
  password: guest
  publisher-confirms: true #如果對異步消息需要回調必須設置爲true
  publisher-returns: true
  listener:
    direct:
      acknowledge-mode: manual
    simple:
      retry:
        enabled: true
        max-attempts: 3
        initial-interval: 2000
      acknowledge-mode: manual
      default-requeue-rejected: false
  template:
    mandatory: true # 觸發returnedMessage回調必須設置mandatory=true, 否則Exchange沒有找到Queue就會丟棄掉消息, 而不會觸發回調

在文件中增加

@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
    RabbitTemplate rabbitTemplate = new RabbitTemplate();
    rabbitTemplate.setConnectionFactory(connectionFactory);
    rabbitTemplate.setChannelTransacted(false);
    rabbitTemplate.setMandatory(true);
    rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
        @Override
        public void confirm(CorrelationData correlationData, boolean ack, String cause) {

            if(ack){
                log.info("消息發送成功:correlationData({}),ack({}),cause({})", correlationData, ack, cause);

            }else{
                System.out.print("----");
            }
        }
    });

    rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
        @Override
        public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
            message.getMessageProperties().setDeliveryMode(MessageProperties.DEFAULT_DELIVERY_MODE);
            log.info("消息丟失:exchange({}),route({}),replyCode({}),replyText({}),message:{}", exchange, routingKey, replyCode, replyText, message);
        }
    });
    return rabbitTemplate;
}

此兩步可以解決生產者丟失消息問題。

 

對於消費者丟失消息

設置手動確認。在消費代碼中try..catch.然後進行手動確認

 

@Component
@RabbitListener(queues = "mall.order.cancel.ttl")
public class CancelOrderReceiver {
    private static Logger LOGGER =LoggerFactory.getLogger(CancelOrderReceiver.class);

    /**
     * 默認情況下,如果沒有配置手動ACK, 那麼Spring Data AMQP 會在消息消費完畢後自動幫我們去ACK
     * 存在問題:如果報錯了,消息不會丟失,但是會無限循環消費,一直報錯,如果開啓了錯誤日誌很容易就吧磁盤空間耗完
     * 解決方案:手動ACK,或者try-catch 然後在 catch 裏面將錯誤的消息轉移到其它的系列中去
     * spring.rabbitmq.listener.simple.acknowledge-mode = manual
     */
    @RabbitHandler
    public void cfgUserReceiveDealy(Long orderId, Message message, Channel channel) throws IOException {
        LOGGER.info("===============接收隊列接收消息====================");
        LOGGER.info("接收時間:{},接受內容:{}", LocalDateTime.now(), orderId.toString(),message.getMessageProperties());
        //通知 MQ 消息已被接收,可以ACK(從隊列中刪除)了
        boolean isAck = true;
        try {
            int f = 1/0;
        } catch (Exception e) {

        
            isAck = false;
            LOGGER.error("============消費失敗,嘗試消息補發再次消費!==============");
            LOGGER.error(e.getMessage());
            //這裏最後一個參數是是否進入隊列。我這裏用法是死信隊列所以必須設置爲false。才能觸發死信
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
        }
        if(isAck){
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }
    }
}

 

下節講解死信隊列設置

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章