【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.mzph.cn/news/595117.shtml

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

相关文章

python封装接口自动化测试套件 !

在Python中&#xff0c;我们可以使用requests库来实现接口自动化测试&#xff0c;并使用unittest或pytest等测试框架来组织和运行测试套件。以下是一个基本的接口自动化测试套件封装示例&#xff1a; 首先&#xff0c;我们需要安装所需的库&#xff1a; pip install requests …

pytest conftest通过fixture实现变量共享

conftest.py scope"module" 只对当前执行的python文件 作用 pytest.fixture(scope"module") def global_variable():my_dict {}yield my_dict test_case7.py import pytestlist1 []def test_case001(global_variable):data1 123global_variable.u…

qt 异常汇总

1. C2338 No Q_OBJECT in the class with the signal (编译源文件 ..\..\qt\labelme-master\src\mainwindow.cpp mainwindow头文件中的类没有Q_OBJECT宏定义&#xff0c;或者其子类或者其他依赖没有Q_OBJECT宏定义。 全部qt类都要写上Q_OBJECT. 2. C2385 对connect的访…

【c++】vector的特性及使用

目录 一、vector的介绍及使用 1、vector迭代器的使用 2、vector的空间增长 3、vector的迭代器失效问题 二、vector的深度剖析与模拟实现 一、vector的介绍及使用 1、vector迭代器的使用 vector的迭代器就是原生态指针。vector的迭代器使用方法与string的迭代器使用方法相…

【CANopen】关于STM32中CanFestival的pdo应用

系列文章目录 文章目录 系列文章目录一、发送1、同步传输2、异步传输 二、接收 使用STM32F407单片机 pdo属于过程数据用来传输实时数据&#xff0c;即单向传输&#xff0c;无需接收节点回应。 一、发送 分为同步传输和异步传输。 1、同步传输 分为循环传输&#xff08;周期…

【12】ES6:模块化

一、JavaScript 模块化 JavaScript 模块化是一种组织和管理 JavaScript 代码的方法&#xff0c;它将代码分割为独立的模块&#xff0c;每个模块都有自己的作用域&#xff0c;并且可以导出和导入功能。模块化可以提高代码的可维护性、可重用性和可扩展性。 在JavaScript中&…

【vue/uniapp】使用 uni.chooseImage 和 uni.uploadFile 实现图片上传(包含样式,可以解决手机上无法上传的问题)

引入&#xff1a; 之前写过一篇关于 uview 1.x 版本上传照片 的文章&#xff0c;但是发现如果是在微信小程序的项目中嵌入 h5 的模块&#xff0c;这个 h5 的项目使用 u-upload 的话&#xff0c;图片上传功能在电脑上正常&#xff0c;但是在手机的小程序上测试就不会生效&#x…

漏洞复现--海康威视IP网络对讲广播系统远程命令执行

免责声明&#xff1a; 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…

职场革命:六款AI助手改写工作效率的故事

引言 在数字化时代&#xff0c;AI助手正快速成为职场的革命者。这些智能助手不仅仅是效率的提升者&#xff0c;它们更是创新的驱动力&#xff0c;重新定义了我们的工作方式。从自动化PPT创建到智能邮件优化&#xff0c;它们的影响深远且多元。本文将深入探讨六款不同领域的AI助…

三维模型数据的几何坐标变换的点云重建并行计算技术方法分析

三维模型数据的几何坐标变换的点云重建并行计算技术方法分析 倾斜摄影三维模型数据的几何坐标变换与点云重建并行计算技术的探讨主要涉及以下几个方面&#xff1a; 1、坐标系定义与转换&#xff1a;在进行坐标变换前&#xff0c;需要确定各个参考系的定义并实现坐标系之间的转…

卷积神经网络|制作自己的Dataset

在编写代码训练神经网络之前&#xff0c;导入数据是必不可少的。PyTorch提供了许多预加载的数据集&#xff08;如FashionMNIST&#xff09;&#xff0c;这些数据集 子类并实现特定于特定数据的函数。 它们可用于对模型进行原型设计和基准测试&#xff0c;加载这些数据集是十分…

阿里云服务器8080端口安全组开通图文教程

阿里云服务器8080端口开放在安全组中放行&#xff0c;Tomcat默认使用8080端口&#xff0c;8080端口也用于www代理服务&#xff0c;阿腾云atengyun.com以8080端口为例来详细说下阿里云服务器8080端口开启教程教程&#xff1a; 阿里云服务器8080端口开启教程 阿里云服务器8080端…

SkyWalking 快速入门

SkyWalking 是一个基于 Java 开发的分布式系统的应用程序性能监视工具&#xff0c;专为微服务、云原生架构和基于容器&#xff08;Docker、K8s、Mesos&#xff09;架构而设计。 一、SkyWalking 简介 SkyWalking 是观察性分析平台和应用性能管理系统。 提供分布式追踪、服务网格…

输入输出流

1.输入输出流 输入/输出流类&#xff1a;iostream---------i input&#xff08;输入&#xff09; o output&#xff08;输出&#xff09; stream&#xff1a;流 iostream&#xff1a; istream类&#xff1a;输入流类-------------cin&#xff1a;输入流类的对象 ostream类…

使用Tensorboard可视化网络结构(基于pytorch)

前言 我们在搭建网络模型的时候&#xff0c;通常希望可以对自己搭建好的网络模型有一个比较好的直观感受&#xff0c;从而更好地了解网络模型的结构&#xff0c;Tensorboard工具的使用就给我们提供了方便的途径 Tensorboard概况 Tensorboard是由Google公司开源的一款可视化工…

【大模型+编程助手】国内编程助手安装与使用(CodeGeeX,Baidu Comate)

百度 Comate (可试用)&#xff1a;https://comate.baidu.com/ 清华CodeGeeX &#xff08;开源&#xff0c;暂时免费&#xff09;&#xff1a;https://codegeex.cn/ 华为&#xff1a;https://devcloud.cn-north-4.huaweicloud.com/codeartside/home?productsnap# 开发平台VScod…

贪吃蛇C语言实现(有源码)

前言 之前学了一点easyx图形库的使用&#xff0c;掌握一些基本用法后就用贪吃蛇来进行实战了&#xff0c;运行视频放在csdn视频那一栏了&#xff0c;之前的烟花也是。 1.头文件 #define _CRT_SECURE_NO_WARNINGS 1 #include<easyx.h> #include<conio.h> #includ…

【Vue2+3入门到实战】(21)认识Vue3、使用create-vue搭建Vue3项目、熟悉项目和关键文件

目录 一、认识Vue31. Vue2 选项式 API vs Vue3 组合式API2. Vue3的优势 二、 使用create-vue搭建Vue3项目1. 认识create-vue2. 使用create-vue创建项目 三、 熟悉项目和关键文件四、总结 一、认识Vue3 1. Vue2 选项式 API vs Vue3 组合式API <script> export default {…

力扣题:高精度运算-1.2

力扣题-1.2 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;415. 字符串相加 解题思想&#xff1a;从后往前遍历两个字符串,然后进行相加即可 class Solution(object):def addStrings(self, num1, num2):""":type num1: str:type …

Navicat 技术干货 | 如何查看关系型数据库(MySQL、PostgreSQL、SQL Server、 Oracle)查询的运行时间

在数据库优化中&#xff0c;理解和监控查询运行时间是至关重要的。无论你是数据库管理员、开发人员或是参与性能调优的人员&#xff0c;知道如何查看查询运行时间能为你的数据库操作提供有价值的参考。本文中&#xff0c;我们将探索几款热门的关系数据库&#xff08;如 MySQL、…