百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

百万级任务重试框架 Fast-Retry(完整的碾碎者框架任务)

toyiye 2024-07-04 09:21 14 浏览 0 评论

  • 前言
  • Fast-Retry
  • What is this?
  • 快速开始
  • 其他

前言

假设你的系统里有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.burukeyou</groupId>
    <artifactId>fast-retry-all</artifactId>
    <version>0.2.0</version>
</dependency>

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

使用重试队列

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

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

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());

使用FastRetryBuilder

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

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);

使用@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(retryWait = @RetryWait(delay = 2))
public CompletableFuture<String> retryTask(){
    return CompletableFuture.completedFuture("success");
}

自定义重试注解

如果不喜欢或者需要更加通用化的贴近业务的重试注解,提供一些默认的参数和处理逻辑,可以自行定义一个重试注解并标记上@FastRetry并指定factory,然后实现AnnotationRetryTaskFactory接口实现自己的构建重试任务的逻辑即可。@FastRetry默认实现就是:FastRetryAnnotationRetryTaskFactory

使用建议

无论是使用以上哪种方式去构建你的重试任务,都建议使用异步重试的方法,即返回结果是CompletableFuture的方法, 然后使用CompletableFuturewhenComplete方法去等待异步重试任务的执行结果。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码