Daily record - SpringBoot integrates RabbitMQ Section 4 (consumer confirmation)

1. Auto mode (automatic ACK)

RabbitMQ is in auto mode by default. When the monitoring consumer method is executed normally, Spring will automatically return ack to RabbitMQ for confirmation; if an exception occurs, it will return nack to RabbitMQ for consumption failure.

application.yml configures RabbitMQ consumer ACK response mode

spring:
  rabbitmq:
    listener:
      simple:
        # none(无应答模式) auto(自动应答模式) manual(手动应答模式)
        acknowledge-mode: auto

Two, none mode (no ACK)

RabbitMQ believes that all messages will be successfully consumed, so RabbitMQ will delete the message immediately after delivering the message

application.yml configures RabbitMQ consumer ACK response mode

spring:
  rabbitmq:
    listener:
      simple:
        # none(无应答模式) auto(自动应答模式) manual(手动应答模式)
        acknowledge-mode: none

3. Manual mode (manual ACK)

After processing the business, the developer calls the API encapsulated by RabbitMQ, and returns an ack to RabbitMQ to confirm the success or failure of the consumption

application.yml configures RabbitMQ consumer ACK response mode

spring:
  rabbitmq:
    listener:
      simple:
        # none(无应答模式) auto(自动应答模式) manual(手动应答模式)
        acknowledge-mode: manual

4. Consumers fail to retry

You can use Spring's own automatic retry mechanism. When an exception occurs in the consumer, retry locally within the consumer; instead of letting the message return to the queue immediately and then let RabbitMQ re-deliver, it will cause the CPU to soar. (This will lead to an infinite loop -> once the message is abnormal, it will be continuously put back into the queue and resent to the consumer).

application.yml configuration
insert image description here

Define queues and exchanges

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RetryQueueConfig {
    
    

    //定义direct类型交换机
    @Bean
    public DirectExchange retryExchange() {
    
    
        return ExchangeBuilder.directExchange("retry.exchange").build();
    }


    //定义持久化队列
    @Bean
    public Queue retryQueue() {
    
    
        return new Queue("retry.queue",true,false,false);
    }

    @Bean
    public Binding retryQueueBinding(Queue retryQueue, DirectExchange retryExchange) {
    
    
        return BindingBuilder.bind(retryQueue).to(retryExchange).with("retry");
    }
}

mock producer

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class RetryQueueTest {
    
    

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //模拟生产者
    @Test
    public void test(){
    
    
        rabbitTemplate.convertAndSend("retry.exchange","retry","模拟消息异常");
    }
}

Console output
The message is deleted after three retries
insert image description here

insert image description here
insert image description here

Recovery strategy after failed retries

In the local retry just now, after reaching the maximum number, the message will be discarded, which is determined by Spring's internal mechanism.

However, in fact, after retrying multiple consumptions and still failing, SpringAMQP provides the MessageRecoverer interface, which defines different recovery strategies that can be used to further process messages:

RejectAndDontRequeueRecoverer: After the retries are exhausted, reject directly and lose the message. is the default processing strategy

ImmediateRequeueMessageRecoverer: After retries are exhausted, nack is returned, and the message is re-queued

RepublishMessageRecoverer: After the retries are exhausted, deliver the failure message to the specified exchange

In actual development, a more elegant solution is RepublishMessageRecoverer, which reposts failure messages to a queue dedicated to storing exception messages, waiting for subsequent manual processing.

RepublishMessageRecoverer policy code

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.amqp.rabbit.retry.RepublishMessageRecoverer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;



@Configuration
public class RepublishMessageRecovererConfig {
    
    

    /*
     * 消息消费失败后的恢复策略:使用RepublishMessageRecoverer策略:重试次数耗尽后,将失败消息投递到指定的交换机
     */
    @Bean
    public MessageRecoverer republishMsgRecoverer(RabbitTemplate rabbitTemplate) {
    
    
        return new RepublishMessageRecoverer(rabbitTemplate, "error.exchange", "error");
    }


    //定义Topic类型交换机
    @Bean
    public TopicExchange errorExchange() {
    
    
        return ExchangeBuilder.topicExchange("error.exchange").build();
    }

    //定义队列
    @Bean
    public Queue errorQueue() {
    
    
        return QueueBuilder.durable("error.queue").build();
    }

    //队列和交换机绑定
    @Bean
    public Binding errorQueueBinding(TopicExchange errorExchange, Queue errorQueue) {
    
    
        return BindingBuilder.bind(errorQueue).to(errorExchange).with("error.#");
    }


}

insert image description here
In this way, after the exception message retries are exhausted, it will be delivered to the specified exception queue and wait for manual processing.

Guess you like

Origin blog.csdn.net/qq407995680/article/details/132108634
Recommended