• Fast-Retry高性能百万级任务重试框架


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

    1.前言

    1.1简介

      Fast-Retry是什么?

      Fast-Retry是一个高性能任务重试框架,支持百万级别任务的并发重试处理。 与主流的Spring-Retry, Guava-Retry等同步重试框架不同,Fast-Retry是一个支持异步重试框架,支持异步任务的重试、超时等待、回调。 Spring-Retry, Guava-Retry均无法支持大批量任务的重试,因为会占用过多线程资源导致大量任务在等待处理,随着任务数的增加,系统吞吐量大大降低,性能指数级降低,Fast-Retry的性能是前者的指数倍。

    1.2项目地址

    https://github.com/burukeYou/fast-retry
    

    1.3 分布式重试服务平台 Easy-Retry

      下面是我之前分享的一篇文章,该篇文章被官方收录至优秀文章页面

    https://mp.weixin.qq.com/s/Rr1oR4ieoYSoU_jLjxybow
    https://blog.csdn.net/qq_34905631/article/details/131187901?spm=1001.2014.3001.5501
    

       Easy-Retry官网优秀文章推荐

    https://www.easyretry.com/pages/db78e2/
    

      easy-retry改名为:Snail Job,代码仓库还在爱祖搭

    https://snailjob.opensnail.com/
    

    2.原理

      利用springBoot的自动装配解析自定义注解等能力,在加上使用了aspectj的动态代理,为指定注解解析生成动态代理类,然后在方法调用时候进行拦截,如果拦截到异常,就利用线程池、多线程、CompletableFuture、队列、生产者+消费者模式提交一个重试任务到线程池中重试执行,然后返回结果,我翻看了Fast-Retry的源码,感兴趣的可以去把它的项目源码拉下来翻一翻,欣赏一下还是会发现一些新大陆的,基本的思路就是这种。

    3.使用

    3.1引入依赖

    <dependency>
      <groupId>io.github.burukeyougroupId>
      <artifactId>fast-retry-allartifactId>
      <version>0.2.0version>
    dependency>
    

    3.2编程式

    3.2.1使用重试队列

            ExecutorService executorService = Executors.newFixedThreadPool(8);
            RetryQueue queue = new FastRetryQueue(executorService);
            RetryTask<String> task = new RetryTask<String>() {
                int result = 0 ;
                @Override
                public long waitRetryTime() {
                    return 2000;
                }
    
                @Override
                public boolean retry() {
                    return ++result < 5;
                }
    
                @Override
                public String getResult() {
                    return  result + "";
                }
            };
            CompletableFuture<String> future = queue.submit(task);
            log.info("任务结束 结果:{}",future.get());
    

    3.2.2使用FastRetryBuilder

            RetryResultPolicy<String> resultPolicy = result -> result.equals("444");
            FastRetryer<String> retryer = FastRetryBuilder.<String>builder()
                    .attemptMaxTimes(3)
                    .waitRetryTime(3, TimeUnit.SECONDS)
                    .retryIfException(true)
                    .retryIfExceptionOfType(TimeoutException.class)
                    .exceptionRecover(true)
                    .resultPolicy(resultPolicy)
                    .build();
    
            CompletableFuture<String> 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);
    

    3.3注解式

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

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

        @FastRetry(retryWait = @RetryWait(delay = 2))
        public String retryTask(){
            return "success";
        }
    

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

        @FastRetry(retryWait = @RetryWait(delay = 2))
        public CompletableFuture<String> retryTask(){
            return CompletableFuture.completedFuture("success");
        }
    

    4.FastRetry、Spring-Retry和Guava-Retry的性能测试对比

      下图是三者的性能对比

    • 测试线程池: 8个固定线程
    • 单个任务逻辑: 轮询5次,隔2秒重试一次,总耗时10秒
    • 未测预计公式: 当我们使用线程池的时候, 一般线程池中 总任务处理耗时 = 任务数/并发度 x 单个任务重试耗时
    任务数FastRetrySpring-RetryGuava-Retry
    110秒10秒10秒
    1010.066秒20.092秒20.078秒
    5010.061秒70.186秒70.168秒
    10010.077秒130.33秒130.31秒
    50010.154秒631.420秒631.53秒
    100010.237秒1254.78秒1256.28秒
    500010.482秒没测预计:6250秒没测预计:6250秒
    1000010.686秒没测预计:12520秒没测预计:12520秒
    10000013.71秒没测预计:125000秒没测预计:125000秒
    50000028.89秒没测预计:625000秒没测预计:625000秒
    100000058.05秒没测预计:1250000秒没测预计:1250000秒

      可以看到即使是处理100万个任务,Fast-Retry的性能也比Spring-Retry和Guava-Retry处理在50个任务时的性能还要快的多的多, 这么快的秘密在于除了是异步,更重要是当别人在重试间隔里休息的时候,Fast-Retry还在不停忙命的工作着。上面这个是官方gitHub上给出的性能测试表格,从他的描述上有一些估计的成份,有一些吹水的成份,测试需要用数据说话,而不是估计大概,用严谨的测试报告才能说明各自性能,所以我觉得这个表格是不严谨的。

    5.总结

      Easy-Retry虽然没有分布式重试的能力,也没有重试监控和可视化展示管理的能力,但是它的实现思路还是值得我们的学习和借鉴的,实现代码写的也是很优雅很耐思的,可以运用在项目上让重试的姿势更加优雅、干净、整洁和美观、性能也有所提升,让你写出帅气的code,保持良好的编码风格和习惯可以避免一些bug的产生,本次分享到此结束,希望我的分享能对你有所启发和帮助,请一键三连,么么么哒!

  • 相关阅读:
    1137. 第N个泰波那契数- 力扣
    Xshell如何连接虚拟机
    迭代器和生成器
    uniapp实现上传文件功能
    C#.NET 国密SM4 CBC 对称加解密 与JAVA互通 ver:20231103
    1027 打印沙漏
    [免费专栏] Android安全之数据存储与数据安全【大集合】
    实现我们mysql的主从复制
    计算机网络高频面试题集锦
    P2672 [NOIP2015 普及组] 推销员 day15
  • 原文地址:https://blog.csdn.net/qq_34905631/article/details/139395818