Spring Retry:优雅地实现方法重试机制

前言

在实际的软件开发中,尤其是在涉及网络请求、数据库操作或外部服务调用的场景下,我们常常会遇到一些临时性故障(Transient Failures),例如网络波动、数据库连接超时、第三方 API 暂时不可用等。面对这些问题,一种常见的解决方案就是自动重试机制

Spring Retry 是 Spring 提供的一个模块,它可以帮助我们以声明式的方式为方法添加重试功能,从而提升系统的健壮性和可用性。


一、什么是 Spring Retry?

Spring Retry 是 Spring 框架中的一个子项目,提供了对方法调用失败后进行自动重试的支持。它不仅支持简单的重试逻辑,还支持重试策略回退策略以及与 Spring AOP 集成,使得我们可以非常方便地在业务代码中加入重试逻辑。


二、Spring Retry 的核心组件

1. RetryTemplate

RetryTemplate 是 Spring Retry 的核心类之一,它封装了重试逻辑的执行过程。你可以通过配置 RetryPolicyBackOffPolicy 来定义重试次数和等待策略。

RetryTemplate retryTemplate = new RetryTemplate();// 设置最多重试3次(包括第一次尝试)
retryTemplate.setRetryPolicy(new SimpleRetryPolicy(3));// 设置固定间隔2秒再重试
retryTemplate.setBackOffPolicy(new FixedBackOffPolicy(2000L));retryTemplate.execute(context -> {// 调用可能会失败的方法someService.doSomething();return null;
});

2. RetryPolicy

定义哪些异常需要重试,以及最大重试次数。常用的有:

  • SimpleRetryPolicy:基于次数的重试。
  • ExceptionClassifierRetryPolicy:根据异常类型决定是否重试。
  • NeverRetryPolicy:从不重试。
  • AlwaysRetryPolicy:无限重试。

3. BackOffPolicy

定义重试之间的等待策略。常用的有:

  • FixedBackOffPolicy:固定时间间隔。
  • ExponentialBackOffPolicy:指数退避策略(推荐)。
  • NoBackOffPolicy:不等待。

4. RetryListener

可以监听重试的不同阶段,比如开始、重试、结束等事件,用于日志记录或监控。


三、使用注解方式实现重试(推荐)

Spring Retry 支持通过注解的方式简化重试逻辑的编写,只需在方法上添加 @Retryable 注解即可。

1. 引入依赖(Maven)

<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId><version>1.3.5</version>
</dependency><!-- 同时需要启用 AspectJ -->
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.7</version>
</dependency>

2. 启用 Retry 功能

在配置类或启动类上加上 @EnableRetry 注解:

@SpringBootApplication
@EnableRetry
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

3. 在方法上使用 @Retryable

@Service
public class MyService {@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 2000))public void doSomething() {// 可能抛出异常的方法体if (Math.random() < 0.7) {throw new RuntimeException("Temporary failure");}System.out.println("Success!");}
}

上面的例子表示:

  • 最多尝试 3 次;
  • 每次失败后等待 2 秒;
  • 默认只对 RuntimeException 进行重试。

你也可以指定特定异常:

@Retryable(value = {IOException.class}, maxAttempts = 5)

或者排除某些异常:

@Retryable(exclude = {SQLException.class})

四、@Retryable 注解参数详解

在使用 Spring Retry 的注解方式时,@Retryable 是最核心的注解之一。它提供了多个可配置项,用于定义方法的重试行为。下面是一个详细的参数说明表:

参数名类型默认值描述
value / includeClass<? extends Throwable>[]{RuntimeException.class}指定需要重试的异常类型,默认对所有 RuntimeException 进行重试。
excludeClass<? extends Throwable>[]{}排除某些异常类型,这些异常不会触发重试。
maxAttemptsint3最大尝试次数(包括第一次调用)。
maxAttemptsExpressionStringnull支持通过 SpEL 表达式动态设置最大尝试次数。
backoffBackoff@Backoff(delay = 1000L)设置退避策略,如固定延迟、指数退避等。
interceptorBeanNameString""自定义拦截器 Bean 名称(不常用)。
labelString""给重试操作添加标签,可用于监听器识别。
statefulbooleanfalse是否为有状态重试(适用于幂等性要求高的场景)。

示例:更复杂的 @Retryable 配置

@Retryable(value = {IOException.class, TimeoutException.class},exclude = SQLException.class,maxAttempts = 5,backoff = @Backoff(delay = 2000, multiplier = 1.5, maxDelay = 10000),stateful = true
)
public void retryableMethod() {// 方法逻辑
}

在这个例子中:

  • 只对 IOExceptionTimeoutException 进行重试;
  • 排除 SQLException
  • 最多重试 5 次;
  • 使用指数退避策略,初始延迟 2 秒,每次乘以 1.5 倍,最长延迟不超过 10 秒;
  • 启用了有状态重试(适合涉及外部状态变更的操作);

五、高级用法:结合监听器

你可以通过自定义监听器来记录每次重试的日志信息:

@Component
public class MyRetryListener implements RetryListener {@Overridepublic <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {System.out.println("Retry: Open");return true;}@Overridepublic <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {System.out.println("Retry: Close");}@Overridepublic <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {System.out.println("Retry: Error occurred, attempt " + context.getRetryCount());}
}

然后注册到 RetryTemplate 中:

retryTemplate.registerListener(new MyRetryListener());

六、注意事项

  1. 幂等性问题:重试操作必须是幂等的,否则重复执行可能导致数据错误。
  2. 事务控制:如果方法处于事务中,注意事务传播行为,避免因重试引发事务冲突。
  3. 性能影响:合理设置重试次数和等待时间,防止系统负载过高。
  4. 异步 vs 同步:Spring Retry 是同步的,如需异步重试需自行结合线程池处理。

七、总结

Spring Retry 是一个轻量但功能强大的重试框架,它通过模板模式和注解方式帮助开发者快速实现方法级别的自动重试。无论是在微服务调用、消息消费、数据库访问等场景中,都可以灵活应用。

合理使用 Spring Retry,可以让我们的系统更加健壮,有效应对各种瞬时故障。

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

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

相关文章

Mysql报错

1.权限问题 MySQL 认证协议不兼容问题解决方案 这个错误表明您的 MySQL 客户端与服务器要求的认证协议不兼容&#xff0c;通常发生在 MySQL 8.0 服务器与旧版客户端之间。 nested exception is org.apache.ibatis.exceptions.PersistenceException: Error querying database. …

小米汽车5月交付量超过28000台,与上月持平

6月1日&#xff0c;小米汽车公布5月交付数据&#xff0c;2025年5月&#xff0c;小米汽车交付量超过28000台&#xff0c;4月官方披露的交付数据也为28000台。 此外&#xff0c;小米汽车5月新增29家门店&#xff0c;全国82城已有298家门店&#xff1b;6月计划新增37家门店&#x…

严格一致性模型

SC 的第二点约束 :store 必须被 所有(包括自身)执行流 同时看到 ,但是不要求写操作“立即”对其他处理器可见&#xff1b;允许写操作延迟一会儿被其他核观察到。 而 严格一致性模型,包括1. store 必须被 所有(包括自身)执行流 同时看到2. 看到的时间 必须是 某个处理器完成写操…

结合 STM32CubeMX 使用 FreeRTOS 实时操作系统

前言 在STM32CubeMX软件出现以后&#xff0c;创建嵌入式项目变得简洁了许多&#xff0c;开发者无需重复编写MCU的外设初始化配置&#xff0c;只需在STM32CubeMX软件中动动鼠标配置完毕&#xff0c;就可以自动生成基于HAL/LL库的Keil项目文件&#xff0c;提高了开发效率。 最近想…

一致性框架:供应链分布式事务问题解决方案

来源&#xff1a;得物技术 一、前言 二、一致性理论基础 1. 一致性模型概述 2. 最终一致性的必要性 三、供应链一致性框架总体架构 1. 一致性框架的核心功能 2. 一致性框架整体框架 3. 一致性框架整体流程 四、一致性框架实现原理 1. 核心组件设计 2. 异步执行实现原…

民国大模型:智能重构下的乱世觉醒与文明转型

引言&#xff1a;当外滩钟声遇见生成式AI 在历史博物馆的数字化展厅中&#xff0c;一幅动态的《民国百景图》正通过全息投影技术演绎十里洋场的繁华与沧桑。这个虚实交融的场景&#xff0c;恰似民国大模型技术的隐喻——以人工智能为纽带&#xff0c;连接起北洋军阀混战与民族…

ROS2 笔记汇总(2) 通信接口

在 ROS 系统中&#xff0c;通信接口&#xff08;Interface&#xff09; 是节点之间传递信息的标准“语言协议”&#xff0c;确保了不同功能节点之间可以正确理解和使用彼此传送的数据内容。我们可以将其理解为“数据结构格式定义”&#xff0c;贯穿于话题&#xff08;Topic&…

微信小程序:将搜索框和表格封装成组件,页面调用组件

一、实现效果 实现搜索框,表格和翻页效果 二、组件实现 1、创建表格组件页面 (1)创建文件 在文件根目录(与pages同级)直接创建components文件夹,并创建表格的页面common-table/index (2)视图层 a、写入表头 循环由主页面传递的columns,数据为字段名label,宽度为设置…

基于贝叶斯学习方法的块稀疏信号压缩感知算法

基于贝叶斯学习方法的块稀疏信号压缩感知算法 BSBL-FM-master/BSBL_BO.m , 15593 BSBL-FM-master/BSBL_FM.m , 12854 BSBL-FM-master/Phi.mat , 131256 BSBL-FM-master/README.md , 3954 BSBL-FM-master/demo.mat , 1610 BSBL-FM-master/demo_fecg.m , 1481 BSBL-FM-master/de…

【Python爬虫】requests知识点讲解

目录 前言1. requests库基础1.1 安装requests1.2 基本导入 2. HTTP请求方法2.1 GET请求2.2 POST请求2.3 其他HTTP方法 3. 请求头设置3.1 User-Agent设置3.2 常用请求头 4. 响应处理4.1 响应内容获取4.2 响应状态码4.3 响应头信息 5. 会话管理5.1 Session对象5.2 Cookie处理 6. …

服务器上安装配置vsftpd

目录 1. 安装vsftpd服务 2、修改配置文件 3. 修改用户白名单 4. 通过ftp客户端命令登录ftp服务器 5. 参考资料 1. 安装vsftpd服务 执行命令安装vsftp服务、和ftp客户端 yum install vsftpd yum install ftp 2、修改配置文件 在服务器上先创建一个系统用户&#xff0c;待…

C#实现图片文字识别

这几年的AI的发展&#xff0c;使得文字识别难度大大降低、精度大大的提高。百度飞浆就是一个非常好的AI框架&#xff0c;而且是开源的。 我们利用百度飞浆就能快速简单的实现文字识别功能&#xff0c;几行代码就可以集成。 其中百度飞浆的PaddleOCR&#xff0c;就是专门针对文…

Android Framework 调用栈

在Android Framework开发中&#xff0c;添加调用栈&#xff08;Call Stack&#xff09;是调试复杂问题&#xff08;如崩溃、死锁或流程追踪&#xff09;的核心手段。 一、Java层调用栈添加 适用于Activity、Service等组件或Framework中的Java代码。 基础方法&#xff1a; 使用…

Ollama安装非系统盘操作方法(2025年6月测试通过)

Ollama是当前部署大模型比较便利的工具&#xff0c;但是默认会将软件和模型都安装到C盘下&#xff0c;导致系统盘爆表&#xff0c;建议将软件和模型都放置在非系统盘。 1. 软件安装在非系统盘 &#xff08;1&#xff09;在D盘下手动创建ollama目录 &#xff08;2&#xff09…

《HTTP权威指南》 第1-2章 HTTP和URL基础

HTTP请求基础 格式化数据块称为HTTP报文 请求报文&#xff1a;从客户端发往服务器的HTTP报文&#xff0c;只有请求起始行请求首部&#xff0c;没有请求主体 响应报文&#xff1a;从服务器发往客户端的报文&#xff0c;包含响应起始行响应首部响应主体 HTTP报文通过传输控制…

9. TypeScript 泛型

TypeScript 中的泛型使开发者能够编写灵活、可重用的代码&#xff0c;同时保持类型安全。它们允许动态定义类型&#xff0c;确保函数、类和接口可以适用于任何数据类型。这有助于避免重复&#xff0c;提高代码的模块化&#xff0c;使其既类型安全又具备适应性。 一、认识泛型 …

Apache Iceberg与Hive集成:分区表篇

一、Iceberg分区表核心概念与Hive集成原理 1.1 分区表在大数据场景的价值 在大规模数据分析中&#xff0c;分区表通过将数据按特定维度&#xff08;如时间、地域、业务类型&#xff09;划分存储&#xff0c;可显著提升查询效率。Apache Iceberg的分区表设计融合了Hive的分区理…

SAST + IAST + DAST 全链路防护体系构建方案

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 1. 生命周期分层嵌入&#xff08;防御纵深&#xff09; 阶段工具防护重点集成触发点编码阶段SAST源码漏洞&#xff08;硬编码密钥、SQL注入模式&#x…

pnpm link如何不踩坑

前提一&#xff1a;我有一个source-project源码库&#xff0c;有一个develop-project项目库。想使用pnpm link对source-project进行本地调试。 前提二&#xff1a;source-project源码库已打包 本地调试详细步骤如下&#xff1a; 1、检查是否配置了系统环境变量&#xff0c;P…

vue3 javascript 多字段求和技巧

在 Vue 3 中&#xff0c;如果你需要在一个组件中处理多个字段的求和&#xff0c;你可以通过计算属性&#xff08;computed properties&#xff09;或者方法&#xff08;methods&#xff09;来实现。这里我将展示两种主要的方法&#xff1a; 方法 1&#xff1a;使用计算属性&am…