RabbitMQ學習筆記:mandatory、publisher-confirms、publisher-return屬性區別

rabbitmq客戶端發送消息首先發送的交換器exchange,然後通過路由鍵routingKey和bindingKey比較判定需要將消息發送到那個隊列queue上;在這個過程有兩個地方消息可能丟失,第一消息發送到交換器exchange的過程,第二消息從交換器exchange發送到隊列queue的過程;

1.publiser-confirm模式可以確保生產者到交換器exchange消息有沒有發送成功
#設置此屬性配置可以確保消息成功發送到交換器
spring.rabbitmq.publisher-confirms=true
2.publisher-return模式可以在消息沒有被路由到指定的queue時將消息返回,而不是丟棄
#可以確保消息在未被隊列接收時返回
spring.rabbitmq.publisher-returns=true

在使用上面的屬性配置時通常會和mandatory屬性配合一起使用:

#指定消息在沒有被隊列接收時是否強行退回還是直接丟棄
spring.rabbitmq.template.mandatory=true

到這裏你可能會有一個疑問,這兩個配置都是指定未找到合適隊列時將消息退回,究竟是如何分別起作用呢?接下來我們看下RabbitAutoConfiguration自動化配置類就清楚了:

        @Bean
        @ConditionalOnSingleCandidate(ConnectionFactory.class)
        @ConditionalOnMissingBean
        public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
            PropertyMapper map = PropertyMapper.get();
            RabbitTemplate template = new RabbitTemplate(connectionFactory);
            MessageConverter messageConverter = (MessageConverter)this.messageConverter.getIfUnique();
            if (messageConverter != null) {
                template.setMessageConverter(messageConverter);
            }
						//設置rabbitmq處理未被queue接收消息的模式
            template.setMandatory(this.determineMandatoryFlag());
            Template properties = this.properties.getTemplate();
            if (properties.getRetry().isEnabled()) {
                template.setRetryTemplate((new RetryTemplateFactory((List)this.retryTemplateCustomizers.orderedStream().collect(Collectors.toList()))).createRetryTemplate(properties.getRetry(), Target.SENDER));
            }

            properties.getClass();
            map.from(properties::getReceiveTimeout).whenNonNull().as(Duration::toMillis).to(template::setReceiveTimeout);
            properties.getClass();
            map.from(properties::getReplyTimeout).whenNonNull().as(Duration::toMillis).to(template::setReplyTimeout);
            properties.getClass();
            map.from(properties::getExchange).to(template::setExchange);
            properties.getClass();
            map.from(properties::getRoutingKey).to(template::setRoutingKey);
            properties.getClass();
            map.from(properties::getDefaultReceiveQueue).whenNonNull().to(template::setDefaultReceiveQueue);
            return template;
        }
				//判定是否將未找到合適queue的消息退回
        private boolean determineMandatoryFlag() {
          	/**
              * 獲取spring.rabbitmq.template.mandatory屬性配置;
              * 這裏面會有三種可能,爲null、false、true
              * 而只有在mandatory爲null時纔會讀取publisher-return屬性值
              **/
            Boolean mandatory = this.properties.getTemplate().getMandatory();
            return mandatory != null ? mandatory : this.properties.isPublisherReturns();
        }

閱讀上面的源碼可以獲取如下信息:

  1. spring.rabbitmq.template.mandatory屬性的優先級高於spring.rabbitmq.publisher-returns的優先級
  2. spring.rabbitmq.template.mandatory屬性可能會返回三種值null、false、true,
  3. spring.rabbitmq.template.mandatory結果爲true、false時會忽略掉spring.rabbitmq.publisher-returns屬性的值
  4. spring.rabbitmq.template.mandatory結果爲null(即不配置)時結果由spring.rabbitmq.publisher-returns確定

GitHub地址:https://github.com/mingyang66/spring-parent/tree/master/doc/rabbitmq

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