网站首页 > 技术教程 正文
在程序的运行过程中一定会出现由于某些原因发生意外的情况,这种时候我们可以通过重新执行来确保程序能够执行成功,Spring框架中有一个小组件spring-retry提供了自动重试的功能。这在错误可能是短暂的(例如瞬间的网络故障)情况下非常有帮助。如果使用原生的Java写法,我们该如何处理重试的呢?
//重试次数
int retryCount = 3;
//重试间隔
int retryInterval = 1000;
while (retryCount > 0) {
try {
//todo 执行业务逻辑
return doSomething();
} catch (Exception e) {
//打印异常信息
System.out.println(e.getMessage());
//重试次数减1
retryCount--;
//等待重试间隔
Thread.sleep(retryInterval);
}
}
上面的代码虽然也可以实现重试的功能,但是代码显得比较臃肿,而且重试的代码和业务代码耦合在一起,如果以后需要修改重试的次数或者重试间隔,就需要修改代码,这样显然是不合理的,那么有没有更好的方式呢?这一次我们介绍使用SpringRetry组件实现重试功能。
1.引入依赖
在pom文件中添加spring-retry和aop的依赖:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.1.11</version>
</dependency>
通过spring-retry实现重试的方式有两种,一种是声明式使用注解,另一种是编程式。
2.声明式
在需要重试的方法上添加@Retryable注解,同时在配置类上加@EnableRetry注解启用重试。下面是一个示例:
启动类
@SpringBootApplication
@EnableRetry
在service中添加方法,方法上添加@Retryable注解,传递一个string类型的参数,当参数为error时模拟发生故障抛出异常。
/**
* @Retryable注解标记需要重试的方法
* retryFor:指定捕获的异常类型
* maxAttempts:最大重试次数
* backoff:重试间隔配置信息
* delay:重试间隔
* multiplier:间隔倍率,间隔倍率是指第一次间隔为delay,第二次间隔为delay*multiplier,第三次间隔为delay*multiplier*multiplier,以此类推
*/
@Retryable(retryFor = Exception.class,maxAttempts = 5,backoff = @Backoff(delay = 500,multiplier=2))
public String test(String msg){
System.out.println(System.currentTimeMillis());
if ("error".equals(msg)){
int i = 1/0;
}
return "success";
}
//output
//1722519362752
//1722519363260
//1722519364272
//1722519366281
//1722519360283
从输出结果可以看出,当程序发生异常时,第二次重试间隔为500ms,第三次重试间隔为1000ms,第四次重试间隔为2000ms,第五次重试间隔为4000ms,以此类推。
也可以通过@Recover注解标记一个方法作为兜底方案,当重试次数达到最大次数后还是执行失败,会调用@Recover注解标记的方法。@Recover注解标记的方法的返回值类型必须和@Retryable注解标记的方法一致,@Recover必须和@Retryable标记的方法在同一个类中。下面是一个示例:
@Recover
public String recover(String msg){
System.out.println(msg);
System.out.println("兜底方法");
return "recover";
}
3.编程式
下面是一个示例:
在配置类中创建一个RetryTemplateBean,交给Spring管理。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.backoff.FixedBackOffPolicy;
import org.springframework.retry.policy.*;
import org.springframework.retry.support.RetryTemplate;
@Configuration
public class RetryConfig {
@Bean
public RetryTemplate retryTemplate(){
//指定退避策略
FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
backOffPolicy.setBackOffPeriod(1000L);
//指定重试策略
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(3);
//创建重试模板
RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.setBackOffPolicy(backOffPolicy);
retryTemplate.setRetryPolicy(retryPolicy);
return retryTemplate;
}
}
在service中注入RetryTemplate,调用execute方法执行需要重试的方法。下面是一个示例:
public void test2(int a) {
try {
Object execute = retryTemplate.execute((RetryCallback<Object, Throwable>) context -> {
//todo 业务逻辑
return a;
});
} catch (Throwable e) {
//todo 处理最终异常
throw new RuntimeException(e);
}
}
如果在业务逻辑处理的过程中发生了异常,会自动进行重试,在这个例子中会重试3次,每次间隔时间为1秒。如果重试3次后还是发生异常,会抛出异常,可以在catch中处理最终异常。
也可以在retryTemplate中添加监听器,监听器会在重试的过程中提供额外的回调,可以利用这些回调处理不同重试中的各种情况,下面是一个示例:
在创建RetryTemplate时注册监听器,监听器重写之后可以重写RetryListener接口中的open,close,onError,onSuccess方法,分别对应重试开始,重试结束,重试发生异常,重试成功时调用。我们这次重写onError方法,当发生异常时打印重试次数。
retryTemplate.registerListener(new RetryListener() {
@Override
public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) {
System.out.println("发生异常,重试次数:" + context.getRetryCount());
}
});
//output
//发生异常,重试次数:1
//发生异常,重试次数:2
//发生异常,重试次数:3
下面是对RetryTemplate的简单介绍:
- RetryTemplate封装了Retry的基本操作,可以指定重试策略,退避策略,监听器等。
- BackOffPolicy定义了重试的退避策略,下面是对它常用的实现类的解释。
- FixedBackOffPolicy:每次重试间隔固定时间。
- ExponentialBackOffPolicy:每次重试间隔时间指数增长。
- NoBackOffPolicy:不进行退避,每次重试间隔时间为0。
- UniformRandomBackOffPolicy:随机间隔时间,每次重试间隔时间为一个随机数。
- RetryPolicy定义了重试的策略,可以指定重试的最大次数,重试的条件等。
- SimpleRetryPolicy:简单的重试策略,可以指定重试的最大次数和捕获的异常。
- CircuitBreakerRetryPolicy:断路器重试策略,可以防止重试次数过多导致系统崩溃。
- TimeoutRetryPolicy:超时重试策略,可以防止重试时间过长导致系统崩溃。
- CompositeRetryPolicy:组合重试策略,可以组合多个重试策略一起使用。
- RetryListener定义了重试的监听器,可以监听重试的开始,结束,异常,成功等事件。
4.应用场景
当程序因为偶尔的网络抖动,数据库锁的获取,消息队列的消费端因为资源不足,调用三方应用时因为对方系统繁忙导致请求失败等原因。
spring-retry提供简单易用的重试机制,可以提高系统的可靠性和健壮性。
猜你喜欢
- 2024-09-25 屡败屡战RETRY第六关关卡攻略 屡屡败屡战的意思
- 2024-09-25 基于redis实现的分布式队列 基于 redis 实现分布式锁是?
- 2024-09-25 .NET 使用 mysql 时 EnableRetryOnFailure() 函数的作用及注意事项
- 2024-09-25 新连载漫画大作导视(十月篇) 十日十月漫画作家
- 2024-09-25 基于guava的重试组件Guava-Retryer
- 2024-09-25 我是怎样得到AO3内容的 我是怎样得到ao3内容的英文
- 2024-09-25 Spring Boot 中使用 spring-retry 轻松解决重试
- 2024-09-25 Java重试利器之Guava-Retryer retry java
- 2024-09-25 springCloud负载均衡机制 springcloud负载均衡策略有哪些
- 2024-09-25 LabVIEW调用DLL中一、二级指针参数及打包exe运行异常的解决办法
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- sd分区 (65)
- raid5数据恢复 (81)
- 地址转换 (73)
- 手机存储卡根目录 (55)
- tcp端口 (74)
- project server (59)
- 双击ctrl (55)
- 鼠标 单击变双击 (67)
- debugview (59)
- 字符动画 (65)
- flushdns (57)
- ps复制快捷键 (57)
- 清除系统垃圾代码 (58)
- web服务器的架设 (67)
- 16进制转换 (69)
- xclient (55)
- ps源文件 (67)
- filezilla server (59)
- 句柄无效 (56)
- word页眉页脚设置 (59)
- ansys实例 (56)
- 6 1 3固件 (59)
- sqlserver2000挂起 (59)
- vm虚拟主机 (55)
- config (61)
本文暂时没有评论,来添加一个吧(●'◡'●)