专栏名称: Java基基
一个苦练基本功的 Java 公众号,所以取名 Java 基基
目录
相关文章推荐
河南日报  ·  AI神器再升级!这次有点猛→ ·  2 天前  
河南日报  ·  AI神器再升级!这次有点猛→ ·  2 天前  
机器之心  ·  DeepSeek一天能赚多少钱?官方突然揭秘 ... ·  2 天前  
AI前线  ·  GPT-4.5 发布!OpenAI ... ·  3 天前  
宝玉xp  ·  看我作为一个 AI 博主是如何用飞书 + ... ·  3 天前  
学习大国  ·  手机里这些细节确认好,别让AI“看透”你 ·  4 天前  
51好读  ›  专栏  ›  Java基基

百万级任务重试框架 Fast-Retry

Java基基  · 公众号  ·  · 2024-06-20 11:55

正文

👉 这是一个或许对你有用 的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入 芋道快速开发平台 知识星球。 下面是星球提供的部分资料:

👉 这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号等等功能:

  • Boot 仓库:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 仓库:https://gitee.com/zhijiantianya/yudao-cloud
  • 视频教程:https://doc.iocoder.cn
【国内首批】支持 JDK 21 + SpringBoot 3.2.2、JDK 8 + Spring Boot 2.7.18 双版本

来源:juejin.cn/post/
7337989768637939739


前言

假设你的系统里有100万个用户,然后你要轮询重试的获取每个用户的身份信息, 如果你还在使用SpringRetry和GuavaRetry 之类的这种单任务的同步重试框架,那你可能到猴年马月也处理不完, 即使加再多的机器和线程也是杯水车薪, 而Fast-Retry正是为这种场景而生

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

Fast-Retry

一个高性能的多任务重试框架,支持百万级任务的异步重试、以及支持编程式和注解声明式等多种使用方式、 也支持自定义结果重试逻辑。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

What is this?

与主流的Spring-Retry, Guava-Retry等单任务同步重试框架不同,Fast-Retry是一个支持异步重试框架,支持异步任务的重试、超时等待、回调。

Spring-Retry, Guava-Retry均无法支持大批量任务的重试,即使加入线程池也无法解决,因为实际每个重试任务都是单独的同步逻辑,然后会会占用过多线程资源导致大量任务在等待处理,随着任务数的增加,系统吞吐量大大降低,性能指数级降低,而Fast-Retry在异步重试下的性能是前者的指数倍。

下图是三者的性能对比

  • 测试线程池: 8个固定线程
  • 单个任务逻辑: 轮询5次,隔2秒重试一次,总耗时10秒
  • 未测预计公式: 当我们使用线程池的时候, 一般线程池中 总任务处理耗时 = 任务数/并发度 x 单个任务重试耗时

可以看到即使是处理100万个任务,Fast-Retry的性能也比Spring-Retry和Guava-Retry处理在50个任务时的性能还要快的多的多属实降维打击,这么快的秘密在于除了是异步,重要的是当别人在重试间隔里休息的时候,Fast-Retry还在不停忙命的工作着。

即使抛开性能不谈, SpringRetry使用繁琐,不支持根据结果的进行重试,GuavaRetry虽然支持,但是又没有提供注解声明式的使用。

快速开始

引入依赖
<dependency>
    <groupId>io.github.burukeyougroupId>
    <artifactId>fast-retry-allartifactId>
    <version>0.2.0version>
dependency>

有以下三种方式去构建我们的重试任务

使用重试队列

RetryTask就是可以配置我们重试任务的一些逻辑,比如怎么重试,怎么获取重试结果,隔多久后重试,在什么情况下重试。它可以帮助我们更加自由的去构建重试任务的逻辑。但如果只是简单使用,强烈建议使用 FastRetryBuilder 或者 @FastRetry 注解

RetryQueue 就是一个执行和调度我们重试任务的核心角色,其在使用上与线程池的API方法基本一致

ExecutorService executorService = Executors.newFixedThreadPool(8);
RetryQueue queue = new FastRetryQueue(executorService);
RetryTask task = new RetryTask() {
    int result = 0 ;
    
    // 下一次重试的间隔
    @Override
    public long waitRetryTime() {
        return 2000;
    }

    // 执行重试,每次重试回调此方法
    @Override
    public boolean retry() {
        return ++result 5;
    }

     // 获取重试结果
    @Override
    public String getResult() {
        return  result + "";
    }
};
CompletableFuture future = queue.submit(task);
log.info("任务结束 结果:{}",future.get());
使用FastRetryBuilder

底层还是使用的 RetryQueue 去处理, 只是帮我们简化了构建RetryTask的逻辑

RetryResultPolicy resultPolicy = result -> result.equals("444");
FastRetryer retryer = FastRetryBuilder.builder()
        .attemptMaxTimes(3)
        .waitRetryTime(3, TimeUnit.SECONDS)
        .retryIfException(true)
        .retryIfExceptionOfType(TimeoutException.class)
        .exceptionRecover(true)
        .resultPolicy(resultPolicy)
        .build()
;

CompletableFuture future = retryer.submit(() -> {
    log.info("重试");
    //throw new Exception("test");
    //int i = 1/0;
    if (0 10){
        throw new TimeoutException("test");
    }
    return "444";
});

String o = future.get();
log.info("结果{}", o);
使用@FastRetry注解

底层还是使用的 RetryQueue 去处理, 只是帮我们简化了构建 RetryTask 的逻辑,并且与Spring进行整合能对Spring的bean标记了 FastRetry 注解的方法进行代理, 提供了重试任务注解声明式的使用方式

  • 依赖Spring环境,所以需要在Spring配置类加上 @EnableFastRetry 注解启用配置 , 这个 @FastRetry 注解的使用才会生效
  • 如果将结果类型使用 CompletableFuture 包装,自动进行异步轮询返回,否则同步阻塞等待重试结果。(推荐)

下面定义等价于 RetryQueue.execute 方法

// 如果发生异常,每隔两秒重试一次
 @FastRetry(retryWait = @RetryWait(delay = 2))
 public String retryTask(){
     return "success";
 }

下面定义等价于 RetryQueue.submit方法,支持异步轮询

@FastRetry






请到「今天看啥」查看全文