Fast-Retry:一个支持百万级多任务异步重试框架【送源码】

前言

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

Fast-Retry

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

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方法去等待异步重试任务的执行结果。

其他

github项目地址

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

maven仓库地址

https://central.sonatype.com/artifact/io.github.burukeyou/fast-retry-all

 福利:

扫码回复【图书】可免费领取图书管理系统源码

图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/679173.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

6.4 cf E(题目难理解)

Problem - E - Codeforces 翻译&#xff1a; 小车在0点&#xff0c;时间为0时开始移动&#xff0c;从0&#xff0c;a1,a2......ak有k1个标志点&#xff0c;对应的时间为0&#xff0c;b1,b2...bk 在任意两个标志间&#xff0c;小车以匀速行驶&#xff0c;所以 vai1​−ai​​…

SpringBoot 统一返回格式

目录 一、为什么要统一返回&#xff1f; 二、全局异常处理代码 三、统一返回对象代码 四、使用方法 五、结果展示 一、为什么要统一返回&#xff1f; 在Spring Boot应用中&#xff0c;为了保持API接口的响应格式统一&#xff0c;通常会采用全局异常处理和自定义返回对象的方…

Sd-CDA (自退化对比域适应框架):解决工业故障诊断中数据不平衡问题

现代工业故障诊断任务常常面临分布差异和双不平衡的双重挑战。现有的域适应方法很少关注普遍存在的双不平衡问题&#xff0c;导致域适应性能差或甚至产生负面迁移。在这项工作中&#xff0c;提出了一种自降级对比域适应&#xff08;SdCDA&#xff09;诊断框架&#xff0c;用于处…

如何实现单例模式及不同实现方法分析-设计模式

这是 一道面试常考题&#xff1a;&#xff08;经常会在面试中让手写一下&#xff09; 什么是单例模式 【问什么是单例模式时&#xff0c;不要答非所问&#xff0c;给出单例模式有两种类型之类的回答&#xff0c;要围绕单例模式的定义去展开。】 单例模式是指在内存中只会创建…

Nginx location 与 Rewrite

Nginx正则表达式 location 通过前缀或正则匹配用户的URL访问路径做页面跳转、访问控制和代理转发 location 大致可以分为三类&#xff1a; 精准匹配&#xff1a;location / {...} 一般匹配&#xff1a;location / {...} 正则匹配&#xff1a;location ~ / {...} location…

外汇天眼:Bitpanda 扩大与德意志银行的合作

金融科技独角兽Bitpanda正在扩大与德意志银行的合作&#xff0c;为德国用户提供实时支付解决方案&#xff0c;以处理进出交易。 这种基于API的账户解决方案将使Bitpanda能够访问德国的IBAN账户&#xff0c;优化和增强用户体验&#xff0c;同时确保信任、速度和效率。 这只是Bi…

通过仪器分类方式修订看监测仪器发展新趋势

随着科技的进步和监测需求的不断升级&#xff0c;监测仪器的分类方式亟需与时俱进。本文旨在探讨《混凝土坝监测仪器系列型谱》中对现有仪器分类方式的修订&#xff0c;以及监测仪器发展的新趋势相关内容。 一、仪器分类方式的修订 传统的仪器分类方式往往基于功能、原理或应用…

太极图形课——渲染——光线追踪实战第一部分呢

根据概念部分我们逐步通过太极实现光线追踪 总共可以分为5步 第一步&#xff1a;如何发射出一道光&#xff1f; 首先明确何为一道光&#xff0c;光从我们眼睛&#xff08;摄像机&#xff09;射出&#xff0c;那么在三维虚拟世界里&#xff0c;我们可以认为这道光就是一条射线…

【微信小程序】事件绑定和事件对象

文章目录 1.什么是事件绑定2.button组件3.事件绑定4.input组件 1.什么是事件绑定 小程序中绑定事件与在网页开发中绑定事件几乎一致&#xff0c;只不过在小程序不能通过on的方式绑定事件&#xff0c;也没有click等事件&#xff0c;小程序中 绑定事件使用bind方法&#xff0c;c…

6个音效、配乐素材网站,免费可商用

视频剪辑必备的6个音效、配乐素材网站&#xff0c;免费下载&#xff0c;剪辑师们赶紧收藏&#xff01; 1、菜鸟图库 音效素材下载_mp3音效大全 - 菜鸟图库 菜鸟图库音效素材免费下载。站内不仅有大量音频素材&#xff0c;还有很多设计、办公、图片、视频等素材。音频素材全部都…

2024年端午节放假通知

致尊敬的客户以及全体同仁&#xff1a; 2024年端午节将至&#xff0c;根据国务院办公厅通知精神&#xff0c;结合公司的实际情况&#xff0c;现将放假事宜通知如下&#xff1a; 2024年6月8日&#xff08;星期六&#xff09;至6月10日&#xff08;星期一&#xff09;&#xff…

Linux文本处理三剑客之awk命令

官方文档&#xff1a;https://www.gnu.org/software/gawk/manual/gawk.html 什么是awk&#xff1f; Awk是一种文本处理工具&#xff0c;它的名字是由其三位创始人&#xff08;Aho、Weinberger和Kernighan&#xff09;的姓氏首字母组成的。Awk的设计初衷是用于处理结构化文本数…

Spring boot实现基于注解的aop面向切面编程

Spring boot实现基于注解的aop面向切面编程 背景 从最开始使用Spring&#xff0c;AOP和IOC的理念就深入我心。正好&#xff0c;我需要写一个基于注解的AOP&#xff0c;被这个注解修饰的参数和属性&#xff0c;就会被拿到参数并校验参数。 一&#xff0c;引入依赖 当前sprin…

OBD诊断协议

上周领导需要做个OBD相关的功能&#xff0c;我对OBD没有啥概念&#xff0c;于是周末就了解下这到底是个啥东西。了解过后发现很简单&#xff0c;其实就是个UDS协议的简化版&#xff0c;OBD是英文On-Board Diagnostics的缩写&#xff0c;中文翻译为“车载自动诊断系统”&#xf…

Redisson 分布式锁 - RLock、RReadWriteLock、RSemaphore、RCountDownLatch(配置、使用、原理)

目录 前言 Redisson 分布式锁 环境配置 1&#xff09;版本说明 2&#xff09;依赖如下 3&#xff09;配置文件如下 4&#xff09;项目配置 RLock 1&#xff09;使用方式 2&#xff09;加锁解释 3&#xff09;加锁时手动设置时间 4&#xff09;加锁时&#xff0c;到…

JVM运行数据区-Java堆

Java堆 堆区&#xff08;Heap区&#xff09;是JVM运行时数据区占用内存最大的一块区域&#xff0c;每一个JVM进程只存在一个堆区&#xff0c;它在JVM启动时被创建&#xff0c;JVM规范中规定堆区可以是物理上不连续的内存&#xff0c;但必须是逻辑上连续的内存。 1、堆区是线程…

王学岗鸿蒙开发(北向)——————(一)鸿蒙开发环境的搭建与ArkTs介绍

1&#xff0c;鸿蒙系统开始研发的时间是在2012年。 2&#xff0c;目前鸿蒙有两个开发:HarmonyOS和OpenHarmony,前者内聚AOSP(Android的东西)&#xff0c;前者是双框架结构&#xff0c;后者不是双框架结构&#xff0c;没有内置安卓。 3&#xff0c;Harmony地址 4&#xff0c;我们…

训练Pytorch深度学习模型出现StopIteration

训练一个深度学习检测模型&#xff0c;突然出现&#xff1a; 是因为next(batch_iterator)&#xff0c;可能迭代器读出来的数据为空。 # load train data# 原先代码images, targets next(batch_iterator)# 更改为&#xff1a;try:images, targets next(batch_iterator)except…

对接钉钉登陆步骤

背景 之前事情较少的时候&#xff0c;帮公司写过一个系统&#xff0c; 这个系统的话主管有要求要对接钉钉登陆。 话不多说我们直接开干。流程 先进入开发者平台点击开发者后台 没有组织的 我们先在手机上先创建一个组织 创建完成后&#xff0c;就可以看到这个组织了 创建…

Michael.W基于Foundry精读Openzeppelin第56期——VestingWallet.sol

Michael.W基于Foundry精读Openzeppelin第56期——VestingWallet.sol 0. 版本0.1 VestingWallet.sol 1. 目标合约2. 代码精读2.1 constructor()2.2 beneficiary() && start() && duration() && receive() payable2.3 released() && releasable(…