@RabbitListener处理重试机制完成后的异常捕获

  • application.properties中配置开启手动签收
java 复制代码
spring.rabbitmq.listener.direct.acknowledge-mode=manual
spring.rabbitmq.listener.simple.acknowledge-mode=manual
  • 定义一个重试器
java 复制代码
@Slf4j
@Configuration
public class RabbitMQRetryConfing {

    @Bean("customRetry")
    public RetryTemplate retryTemplate() {
        RetryTemplate retryTemplate = new RetryTemplate();
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
        retryPolicy.setMaxAttempts(3); // 设置重试次数
        retryTemplate.setRetryPolicy(retryPolicy);

        FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
        backOffPolicy.setBackOffPeriod(2000); // 重试间隔,单位:毫秒
        retryTemplate.setBackOffPolicy(backOffPolicy);

        // 添加 RetryListener 以观察重试过程
        retryTemplate.registerListener(new RetryListener() {
            @Override
            public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
                return true;
            }

            @Override
            public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
            }

            @Override
            public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
                //春姐,这里可以灵活配置重试失败后的回调,例如发送告警、更新数据库状态等
                if (context.getRetryCount() >= retryPolicy.getMaxAttempts()) {
                    int retryCount = context.getRetryCount();
                    // 当重试次数耗尽时进行处理
                    log.info("已达到最大重试次数{}次,丢弃本次任务",retryCount);
                }
            }
        });

        return retryTemplate;
    }
}

这个重试器可以配置最大重试次数、重试之间间隔次数等策略配置,调用重试器的execute方法可以进行队列消费,如果在执行一次任务期间发生了异常,则会根据配置的重试次数以及间隔时间自动触发下一次重试,每一次重试都是在同一个线程中执行完成的,并且RetryTemplate会为每一次重试失败进行回调,提供了诸如 onOpen、onClose、onError等回调时机。

  • RabbitMQ监听器回调方法
java 复制代码
	@Autowired
    @Qualifier("customRetry")
    private RetryTemplate retryTemplate;

    //queues消费的队列  ackMode确认模式 MANUAL 手动确认
    @RabbitListener(queues = "q",ackMode = "MANUAL")
    @Override
    public void onMessage(Message message, Channel channel)   {
        try {
            retryTemplate.execute(new RetryCallback<Object, Throwable>() {
                @Override
                public Object doWithRetry(RetryContext retryContext) throws Throwable {
                    // 消息的唯一标识id
                    long deliveryTag = message.getMessageProperties().getDeliveryTag();
                    log.info("接收到mq信息" + new String(message.getBody()));
                    try{
                        //todo 开始业务处理
                        String msg = new String(message.getBody());
                        Integer articleId = Integer.parseInt(msg);
                        newsService.pullNews(articleId);
                        // 手动签收的第一个参数为消息的唯一标识id、第二个参数表示是否批量签收
                        channel.basicAck(deliveryTag,false);
                        log.info("消费mq消息成功,articleId为:{}",articleId);
                        return null;
                    }catch (Throwable e){
                        log.error(String.format("失败,异常信息为:%s",new String(message.getBody()),e.getMessage()));
                        //重新抛出异常  触发重试机制
                        throw e;
                    }
                    finally {
                        //重试次数达到限制
                        log.error(String.format("失败",new String(message.getBody())));
                        //不重新入队,发送到死信队列
                        // 手动拒绝签收的第一个参数为消息id、
                        // 第二个参数表示是否批量签收
                        // 第三个参数消息是否重回队列
                        channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
                    }
                }
            });
        } catch (Throwable throwable) {
            log.info("执行回调重试上下文出现异常");
        }

    }

这样,当耗尽完重试次数之后就会被回调到onError方法中执行自定义的异常逻辑处理。

相关推荐
x***r15113 分钟前
jdk-11.0.16.1_windows使用步骤详解(附JDK 11环境变量配置与验证教程)
java·开发语言·windows
luck_bor1 小时前
File类&递归作业
java·开发语言
武子康1 小时前
Java-07 深入浅出 MyBatis数据库一对多关系模型实战:表结构设计与查询实现
java·后端
花椒技术2 小时前
企业内部 Agent 落地复盘:Gateway、Skill 和二次确认如何串起受控业务执行
后端·agent·ai编程
我是一颗柠檬4 小时前
【MySQL全面教学】MySQL事务与ACID Day9(2026年)
数据库·后端·mysql
枕星而眠4 小时前
数据结构八大排序详解(一):四大简单排序
c语言·数据结构·c++·后端
IT_陈寒4 小时前
React useEffect闭包陷阱差点把我整失业了
前端·人工智能·后端
努力努力再努力wz4 小时前
【Qt入门系列】:按钮组件全解析:从 QAbstractButton 到快捷键事件、单选与复选机制
c语言·开发语言·数据结构·c++·git·qt·github
苍何5 小时前
爆肝两周,我把 Codex 最全实战指南开源了
后端
skywalk81635 小时前
言知(Yanzhi)系统提升建议报告和完工报告 by AutoCoder
开发语言·编程