【SpringBoot框架篇】34.使用Spring Retry完成任务的重试

文章目录

  • 简要
  • 1.为什么需要重试?
  • 2.添加maven依赖
  • 3.使用@Retryable注解实现重试
  • 4.基于RetryTemplate模板实现重试

简要

Spring实现了一套重试机制,功能简单实用。Spring Retry是从Spring Batch独立出来的一个功能,已经广泛应用于Spring Batch,Spring Integration, Spring for Apache Hadoop等Spring项目。

本文将讲述如何使用Spring Retry及其实现原理。

1.为什么需要重试?

在调用一些第三方接口时候可能会因为网络或者服务方异常导致请求失败,这个时候可以通过重试解决这种问题。

以下面的简单的例子来了解 Retry的功能,下面有个doTask函数,执行该函数的时候如果出现异常则需要重试任务

  • 1.CountDownLatch 用于在主线程用于等待线程池中的任务完成
  • 2.AtomicInteger 类型用于计算重试次数
  • 3.ScheduledExecutorService用于定时执行需要重试的任务,如果没有异常则第一次执行完任务则会关闭线程池
  • 4.doTask函数中通过 1/0故意造成异常
    public static boolean doTask() {try {System.out.println(1/0);return true;} catch (Exception e) {return false;}}/*** 通过ScheduledExecutor定时器实现低配版本的重试机制* @param args* @throws Exception*/public static void main(String[] args) throws Exception {CountDownLatch countDownLatch = new CountDownLatch(1);AtomicInteger count = new AtomicInteger(0);//设置重试的次数int retryNumber = 3;//创建单线程的定时任务处理器ScheduledExecutorService scheduledThreadPool = Executors.newSingleThreadScheduledExecutor();//(参数1=执行内容,参数2=初始延迟时间,参数3=任务间隔时间,参数4=时间单位)scheduledThreadPool.scheduleAtFixedRate(() -> {boolean flag = doTask();//业务是否处理成功,成功则关闭线程池if (flag || count.get() == retryNumber) {//执行成功或者已达到执行次数则关闭线程池scheduledThreadPool.shutdownNow();countDownLatch.countDown();;}else{log.info("第{}次重试任务", count.get()+1);count.getAndIncrement();}}, 0, 1, TimeUnit.SECONDS);//等待线程池中的任务完成countDownLatch.await();}

在这里插入图片描述
把doTask函数中的导致异常的代码注释再运行可以看到控制台没有打印重试的信息

从上面代码可以看出写一个任务重试的工具不难,感兴趣的同学可以通过AOP代理的方式自己实现基于注解的重试功能,Spring官方的Retry模块里有通过Aop加注解的方式实现重试功能,Aop玩腻了,我就不造轮子了。。

2.添加maven依赖

由于retry依赖中没有包含aspectj相关依赖,所以需要单独引用aspectj

    <!-- https://mvnrepository.com/artifact/org.springframework.retry/spring-retry --><dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId><version>1.3.4</version></dependency><!--aop切面--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>

3.使用@Retryable注解实现重试

3.1.需要在springboot启动添加@EnableRetry注解开启对Retry的支持

@EnableRetry
@SpringBootApplication
public class RetryApplication {
}

3.2.定义需要重试任务的异常类型

public class CustomRecoveryException extends Exception{public CustomRecoveryException(String error){super(error);}
}

3.3.在需要任务重试的函数上面添加注解

  • value属性表示在哪些异常的情况下才会去重试,多个类型用,隔开。
  • maxAttempts属性设置执行次数,默认值为3则表示异常后只会重试两次
  • backoff属性设置下次重试的延迟时间,默认值为1000ms(1秒)。
@Slf4j
@Service
public class RetryServer  {@Retryable(value = {CustomRecoveryException.class, IOException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000))public void retryTest() throws CustomRecoveryException {log.info("retryTest,当前时间:{}",LocalDateTime.now());throw new CustomRecoveryException("test retry error");}

3.4.通过@Recover定义降级处理的函数
返回值需要和重试的任务一致,要不然会抛出异常。

    @Recoverpublic void fallback(Throwable throwable) {// 降级处理逻辑log.error("fallback,Error msg:{}",throwable.getMessage());return "fallback";}} 

3.5.使用junit进行测试

@SpringBootTest
class RetryApplicationTests {@Autowiredprivate RetryServer retryServer;@Testvoid contextLoads() throws CustomRecoveryException {retryServer.retryTest();}
}    

可以看到控制台只打印了三次日志,从这能确认任务共执行了三次,只重试了两次。
在这里插入图片描述

4.基于RetryTemplate模板实现重试

4.1.配置RetryTemplate重试的策略

@EnableRetry
@SpringBootApplication
public class RetryApplication {public static void main(String[] args) {SpringApplication.run(RetryApplication.class, args);}@Beanpublic RetryTemplate retryTemplate() {final SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy();//设置最多执行次数, 包含第一次执行,下面配置成3,则第一次执行出现异常后最多会再重试2次simpleRetryPolicy.setMaxAttempts(3);final FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();//设置重试间隔时间  单位 msfixedBackOffPolicy.setBackOffPeriod(1000L);return RetryTemplate.builder().customPolicy(simpleRetryPolicy).customBackoff(fixedBackOffPolicy).build();}
}

4.2.添加任务重试失败之后的降级处理回调函数

@Slf4j
@Component
public class CustomRecoveryCallback implements RecoveryCallback<String> {@Overridepublic String recover(RetryContext retryContext) {log.error("fallback,retryCount:{},error msg:{}",retryContext.getRetryCount(),retryContext.getLastThrowable().getMessage());return "fallback";}
}

4.3.通过retryTemplate.execute执行需要重试的任务

@Slf4j
@Service
public class RetryServer  {@Autowiredprivate RetryTemplate retryTemplate;@Autowiredprivate CustomRecoveryCallback customRecoveryCallback;public void retryTemplateTest() {//第一个参数是只需要执行的方法,第二个参数是降级处理方法retryTemplate.execute(f->function(),customRecoveryCallback);}/*** 具体的执行任务*/public String function(){log.info("retryTemplateTest,当前时间:{}",LocalDateTime.now());throw new RuntimeException("test retry error");}}

4.4.使用junit进行测试

@SpringBootTest
class RetryApplicationTests {@Autowiredprivate RetryServer retryServer;@Testvoid contextLoads() {retryServer.retryTemplateTest();}}

可以看到测试得到的结果和注解的方式是一样的,都只执行了三次任务。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法巡练day04Leetcode24交换节点19删除倒数节点142环形链表

今天学习的文章和视频链接 https://www.bilibili.com/video/BV1YT411g7br/?vd_source8272bd48fee17396a4a1746c256ab0ae https://www.bilibili.com/video/BV1if4y1d7ob/?vd_source8272bd48fee17396a4a1746c256ab0ae 24两两交换链表中的节点 给你一个链表&#xff0c;两两…

ASP.NET Core基础之图片文件(一)-WebApi图片文件上传到文件夹

阅读本文你的收获&#xff1a; 了解WebApi项目保存上传图片的三种方式学习在WebApi项目中如何上传图片到指定文件夹中 在ASP.NET Core基础之图片文件(一)-WebApi访问静态图片文章中&#xff0c;学习了如何获取WebApi中的静态图片&#xff0c;本文继续分享如何上传图片。 那么…

八皇后问题(C语言/C++)超详细讲解/由浅入深---深入八皇后问题

介绍引入 在计算机科学中&#xff0c;八皇后问题是一个经典的回溯算法问题。这个问题的目标是找出一种在8x8国际象棋棋盘上放置八个皇后的方法&#xff0c;使得没有任何两个皇后能够互相攻击。换句话说&#xff0c;每一行、每一列以及对角线上只能有一个皇后。 想象一下&…

为什么大学c语言课不顺便教一下Linux,Makefile

为什么大学c语言课不顺便教一下Linux&#xff0c;Makefile&#xff0c;git&#xff0c;gdb等配套工具链呢? 在开始前我有一些资料&#xff0c;是我根据自己从业十年经验&#xff0c;熬夜搞了几个通宵&#xff0c;精心整理了一份「Linux的资料从专业入门到高级教程工具包」&…

Docker 网络管理

一、Docker网络简介 Docker网络是容器化应用程序的重要组成部分&#xff0c;它使得容器之间可以互相通信和连接&#xff0c;同时也提供了容器与外部环境之间的隔离和连接。 二、Docker网络网络模式 Docker 提供了多种网络模式&#xff0c;可以通过docker network ls 命令查看…

MySQL——事物

目录 一.发现问题 二.什么时事物 三.事务提交方式 四.事物的常规操作方式 五. 事务隔离级别 1.如何理解隔离性 2.隔离级别 3.查看与设置隔离性 4.读未提交【Read Uncommitted】 5.读提交【Read Committed】 6.可重复读【Repeatable Read】 7.串行化【serializabl…

Unity游戏资源更新(AB包)

目录 前言&#xff1a; 一、什么是AssetBundle 二、AssetBudle的基本使用 1.AssetBundle打包 2.BuildAssetBundle BuildAssetBundleOptions BuildTarget 示例 3.AssetBundle的加载 LoadFromFile LoadFromMemory LoadFromMemoryAsync UnityWebRequestAsssetBundle 前…

QProgressDialog用法及结合QThread用法,四种线程使用

1 QProgressDialog概述 QProgressDialog类提供耗时操作的进度条。 进度对话框用于向用户指示操作将花费多长时间&#xff0c;并演示应用程序没有冻结。此外&#xff0c;QPorgressDialog还可以给用户一个中止操作的机会。 进度对话框的一个常见问题是很难知道何时使用它们;操作…

Linux shell编程学习笔记38:history命令

目录 0 前言 1 history命令的功能、格式和退出状态1.1 history命令的功能1.2 history命令的格式1.3退出状态2 命令应用实例2.1 history&#xff1a;显示命令历史列表2.2 history -a&#xff1a;将当前会话的命令行历史追加到历史文件~/.bash_history中2.3 history -c&#xf…

如何做好档案数字化前的鉴定工作

要做好档案数字化前的鉴定工作&#xff0c;可以按照以下步骤进行&#xff1a; 1. 确定鉴定目标&#xff1a;明确要鉴定的档案的内容、数量和性质&#xff0c;确定鉴定的范围和目标。 2. 进行档案清点&#xff1a;对档案进行全面清点和登记&#xff0c;包括数量、种类、状况等信…

【Linux】基本指令了解(一)

&#x1f497;个人主页&#x1f497; ⭐个人专栏——数据结构学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 导读&#xff1a;1. 认识Linux1.1 什么是Linux1.2 Linux特点 2. ls指令3. pwd命令4. cd 指令5. touch命令6. mkdir指令7. …

<JavaEE> TCP 的通信机制(二) -- 连接管理(三次握手和四次挥手)

目录 TCP的通信机制的核心特性 三、连接管理 1&#xff09;什么是连接管理&#xff1f; 2&#xff09;“三次握手”建立连接 1> 什么是“三次握手”&#xff1f; 2> “三次握手”的核心作用是什么&#xff1f; 3&#xff09;“四次挥手”断开连接 1> 什么是“…

听GPT 讲Rust源代码--library/panic_unwind

File: rust/library/panic_unwind/src/seh.rs 在Rust源代码中&#xff0c;rust/library/panic_unwind/src/seh.rs这个文件的作用是实现Windows操作系统上的SEH&#xff08;Structured Exception Handling&#xff09;异常处理机制。 SEH是Windows上的一种异常处理机制&#xff…

Mysql 动态链接库配置步骤+ 完成封装init和close接口

1、创建新项目 动态链接库dll 2、将附带的文件都删除&#xff0c;创建LXMysql.cpp 3、项目设置 3.1、预编译头&#xff0c;不使用预编译头 3.2、添加头文件 3.3、添加类 3.4、写初始化函数 4、项目配置 4.1、右键解决方案-属性-常规-输出目录 ..\..\bin 4.2、生成lib文件 右…

3D视觉-相机选用的原则

鉴于不同技术方案都有其适用的场景&#xff0c;立体相机的选型讲究的原则为“先看用途&#xff0c;再看场景&#xff0c;终评精度”&#xff0c;合适的立体相机在方案中可以起到事半功倍的效果。从用途上来进行划分&#xff0c;三维视觉方案主要应用在两个方向&#xff1a;测量…

Linux 进程(六) 环境变量

main函数参数&#xff1a; 这是一个常见的main函数&#xff0c;那么main函数可以带参吗&#xff1f; int main() {return 0; } 答案是可以的&#xff01; 我们先看这样一段代码&#xff0c;首先给main函数带上两个参数。 然后我们来看输出的结果。 这样一组字符串是命令行解释…

【AI】一文读懂大模型套壳——神仙打架?软饭硬吃?

目录 一、套壳的风波此起彼伏 二、到底什么是大模型的壳 2.1 大模型的3部分&#xff0c;壳指的是哪里 大模型的内核 预训练&#xff08;Pre-training&#xff09; 调优&#xff08;Fine-tuning&#xff09; 2.2 内核的发展历程和万流归宗 2.3 套壳不是借壳 三、软饭硬…

Ubuntu 常用命令之 locate 命令用法介绍

&#x1f525;Linux/Ubuntu 常用命令归类整理 locate命令是在Ubuntu系统下用于查找文件或目录的命令。它使用一个预先构建的数据库&#xff08;通常由updatedb命令创建&#xff09;来查找文件或目录&#xff0c;因此它的查找速度非常快。 plocate 安装 locate 不是 Ubuntu 系…

语音AI小夜灯项目

一、项目简介 使用ESP32-S3N8R8模块作为主控芯片&#xff0c;S3内核增加了用于加速神经网络计算和信号处理等的指令&#xff0c;这使得我们可以使用它来快速解析训练好的语音模型进行语音识别的功能。 二、原理解析 本项目由四个部分组成&#xff0c;电源部分、LED照明部分、…

Spring Cloud Gateway 常见过滤器的基本使用

目录 1. 过滤器的作用 2. Spring Cloud Gateway 过滤器的类型 2.1 内置过滤器 2.1.1 AddResponseHeader 2.1.2 AddRequestHeader 2.1.3 PrefixPath 2.1.4 RequestRateLimiter 2.1.5 Retry 2.2 自定义过滤器 1. 过滤器的作用 过滤器通常用于拦截、处理或修改数据流和事…