Springboot (四) RabbitMQ消费者重试机制(spring retry)

1. 什么时候应该用MQ?
2. Rabbit 基础知识
3. docker 安装 RabbitMQ
4. Springboot (四) RabbitMQ入门

Springboot (四) RabbitMQ消费者重试机制(spring retry实现)

项目下载地址 Springboot-RabbitMQ-demo

1. 新建配置类 ,上代码

重点在于,retryTemplate 设置重试 。

@Slf4j
@Configuration
public class RabbitRetryConfig {

    @Autowired
    ConnectionFactory rabbitConnectionFactory;

    //@Bean  缓存连接池
    //public CachingConnectionFactory rabbitConnectionFactory

    @Autowired
    RabbitProperties properties;
    
    // 存在此名字的bean 自带的容器工厂会不加载,如果想自定义来区分开 需要改变bean 的名称
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
        SimpleRabbitListenerContainerFactory containerFactory = new SimpleRabbitListenerContainerFactory();
        containerFactory.setConnectionFactory(rabbitConnectionFactory);
        // 并发消费者数量
        containerFactory.setConcurrentConsumers(1);
        containerFactory.setMaxConcurrentConsumers(20);
        // 自动应答
        containerFactory.setAcknowledgeMode(AcknowledgeMode.AUTO);
        //containerFactory.setMessageConverter(new Jackson2JsonMessageConverter());
        containerFactory.setChannelTransacted(true);
        containerFactory.setAdviceChain(
                RetryInterceptorBuilder
                        .stateless()
                        .recoverer(new RejectAndDontRequeueRecoverer())
                        .retryOperations(rabbitRetryTemplate())
                        .build()
        );
        return containerFactory;
    }

    @Bean
    public RetryTemplate rabbitRetryTemplate() {
        RetryTemplate retryTemplate = new RetryTemplate();

        // 设置监听(不是必须)
        retryTemplate.registerListener(new RetryListener() {
            @Override
            public <T, E extends Throwable> boolean open(RetryContext retryContext, RetryCallback<T, E> retryCallback) {
                // 执行之前调用 (返回false时会终止执行)
                return true;
            }

            @Override
            public <T, E extends Throwable> void close(RetryContext retryContext, RetryCallback<T, E> retryCallback, Throwable throwable) {
                // 重试结束的时候调用 (最后一次重试 )
            }

            @Override
            public <T, E extends Throwable> void onError(RetryContext retryContext, RetryCallback<T, E> retryCallback, Throwable throwable) {
                //  异常 都会调用
                log.error("-----第{}次调用", retryContext.getRetryCount());
            }
        });

        // 个性化处理异常和重试 (不是必须)
        /* Map<Class<? extends Throwable>, Boolean> retryableExceptions = new HashMap<>();
        //设置重试异常和是否重试
        retryableExceptions.put(AmqpException.class, true);
        //设置重试次数和要重试的异常
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(5,retryableExceptions);*/

        retryTemplate.setBackOffPolicy(backOffPolicyByProperties());
        retryTemplate.setRetryPolicy(retryPolicyByProperties());
        return retryTemplate;
    }

    @Bean
    public ExponentialBackOffPolicy backOffPolicyByProperties() {
        ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
        long maxInterval = properties.getListener().getSimple().getRetry().getMaxInterval().getSeconds();
        long initialInterval = properties.getListener().getSimple().getRetry().getInitialInterval().getSeconds();
        double multiplier = properties.getListener().getSimple().getRetry().getMultiplier();
        // 重试间隔
        backOffPolicy.setInitialInterval(initialInterval * 1000);
        // 重试最大间隔
        backOffPolicy.setMaxInterval(maxInterval * 1000);
        // 重试间隔乘法策略
        backOffPolicy.setMultiplier(multiplier);
        return backOffPolicy;
    }

    @Bean
    public SimpleRetryPolicy retryPolicyByProperties() {
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
        int maxAttempts = properties.getListener().getSimple().getRetry().getMaxAttempts();
        retryPolicy.setMaxAttempts(maxAttempts);
        return retryPolicy;
    }

}

设计思路,实现消费者拦截器的容器工厂,增加 重试类 来设置重试参数。
本例子,获取了Rabbitproperties 的配置,也可以自定义。 消息在被消费者获取后,重试3次后,将会过期,我设置了死信队列,将重试处理不了的消息 了 路由到了死信队列中 。死信队列的消息需要人工干预处理。

2. 实现例子

我们要新增一个 正常的交换机 (exchangge_normal
和 死信交换机 (exchangge_failure),绑定正常队列 (queue_normal)和死信队列(queue_failure)

开始动手使用RabbitMQ 管理页面 创建队列和交换机, routingkey 统一用 key来表示 。

队列:

正常队列 需要设置 ”x-dead-letter-exchange”参数
在这里插入图片描述
死信队列 :
在这里插入图片描述

交换机:

在这里插入图片描述
在这里插入图片描述

交换机和队列关系绑定好之后,我们上一个简单的消费者代码,实现一个简单的异常,让消息无法正常消费。
   /**
     * 接受指定队列的消息
     */
    @RabbitListener(queues = {"queue_normal"})
    public void consumer2(Message message, Channel channel)  {
        // 消息内容
        String body = new String(message.getBody());
        log.error(body);
        int i = 1 / 0;
    }
3. 测试代码:

启动消费者进行监听消息,手动在Rabbit管理页面发送一条消息。
队列初始化状态,一条待消费消息。
在这里插入图片描述
启动消费者,控制台打印日志,因为我在监听代码中加了次数日志;
在这里插入图片描述
查看队列消息数量变化,消息被转发到了死信队列
在这里插入图片描述
我们去看看消息的头信, 来源是正常消息队列。例子成功!
在这里插入图片描述

  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Spring Boot中使用RabbitMQ进行消息重试可以通过以下步骤进行设置: 1. 首先,确保在项目的依赖中添加了RabbitMQ的starter依赖。可以在项目的pom.xml文件中添加如下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> ``` 2. 在application.properties(或application.yml)文件中配置RabbitMQ连接信息。例如: ```properties spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest ``` 3. 创建一个RabbitMQ的消息监听器,用于接收和处理消息。可以使用`@RabbitListener`注解标记监听方法,例如: ```java @Component public class MyMessageListener { private static final String QUEUE_NAME = "my-queue"; @RabbitListener(queues = QUEUE_NAME) public void handleMessage(String message) { // 处理消息的逻辑 } } ``` 4. 在处理消息的逻辑中,可以使用Spring Retry库来实现消息的重试机制。首先,添加Spring Retry的依赖到项目的pom.xml文件中: ```xml <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> ``` 5. 在消息处理方法中,使用`@Retryable`注解来标记方法,并配置重试策略。例如: ```java @Component public class MyMessageListener { private static final String QUEUE_NAME = "my-queue"; @RabbitListener(queues = QUEUE_NAME) @Retryable( value = {AmqpException.class}, maxAttempts = 3, backoff = @Backoff(delay = 5000) ) public void handleMessage(String message) { // 处理消息的逻辑 } @Recover public void recover(AmqpException e) { // 重试达到最大次数后的处理逻辑 } } ``` 在上述代码中,`@Retryable`注解用于标记消息处理方法,`maxAttempts`属性表示最大重试次数,`backoff`属性表示重试间隔时间(这里设置为每次重试间隔5秒)。`@Recover`注解用于标记重试达到最大次数后的处理方法。 这样,当消息处理发生异常时,Spring Retry会自动进行重试,直到达到最大重试次数或处理成功为止。 以上就是在Spring Boot中设置RabbitMQ消息重试的基本步骤。你可以根据实际需求调整重试次数、重试间隔等参数。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值