spring-boot:1.5.3.RELEASE,spring-retry-1.2.0.RELEASE
使用方法
引入pom
// 版本号继承spring-boot依赖管理的pomorg.springframework.retry spring-retryorg.aspectj aspectjweaver
启用重试
@Configuration
@importResource(locations = { "classpath*:spring/app-context-*" })
@EnableRetry
public class AppContext {
}
注解需要重试的方法
@Retryable(value = RuntimeException.class, maxAttempts = 3,backoff = @Backoff(delay = 10L, multiplier = 1))
public boolean myRetryableMethod(){
...
}
注解属性含义
Retryable
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface Retryable {
String interceptor() default "";
Class extends Throwable>[] value() default {};
Class extends Throwable>[] include() default {};
Class extends Throwable>[] exclude() default {};
String label() default "";
boolean stateful() default false;
int maxAttempts() default 3;
String maxAttemptsexpression() default "";
Backoff backoff() default @Backoff();
String exceptionexpression() default "";
}
Backoff
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@import(RetryConfiguration.class)
@documented
public @interface Backoff {
long value() default 1000;
long delay() default 0;
long maxDelay() default 0;
double multiplier() default 0;
String delayexpression() default "";
String maxDelayexpression() default "";
String multiplierexpression() default "";
boolean random() default false;
}
案例
默认retry
@Component
public class MyTask {
@Retryable
public void doExecute(){
System.out.println("## current Date:" + new Date());
throw new RuntimeException("my test");
}
}
输出结果
## current Date:Sat Aug 29 21:54:55 CST 2020 ## current Date:Sat Aug 29 21:54:56 CST 2020 ## current Date:Sat Aug 29 21:54:57 CST 2020 2020-08-29 21:55:00,319 INFO [main] com.dianwoba.common.datasource.DataSourceAspect:invoke:32 restore database connection Exception in thread "main" java.lang.RuntimeException: my test ...
stateful
源码相同,注解增加属性配置
@Retryable( stateful = true )
public void doExecute(){
输出结果
## current Date:Sat Aug 29 21:58:56 CST 2020 2020-08-29 21:58:57,557 INFO [main] com.dianwoba.common.datasource.DataSourceAspect:invoke:32 restore database connection Exception in thread "main" java.lang.RuntimeException: my test // 没有重新抛出异常触发重试
该参数为false时会重试3次后抛出异常,重试期间不会重新抛出异常。参数为true时则重试期间也会重新抛出异常导致重试失败不再继续重试
backoff.multiplier
注解属性配置
@Retryable( backoff = @Backoff( delay = 1000, multiplier = 2), maxAttempts = 10)
输出结果
## current Date:Sat Aug 29 23:06:50 CST 2020 ## current Date:Sat Aug 29 23:06:51 CST 2020 ## current Date:Sat Aug 29 23:06:53 CST 2020 ## current Date:Sat Aug 29 23:06:57 CST 2020 ## current Date:Sat Aug 29 23:07:05 CST 2020 ## current Date:Sat Aug 29 23:07:21 CST 2020 ## current Date:Sat Aug 29 23:07:51 CST 2020 ## current Date:Sat Aug 29 23:08:21 CST 2020 ## current Date:Sat Aug 29 23:08:51 CST 2020 ## current Date:Sat Aug 29 23:09:21 CST 2020 2020-08-29 23:09:21,949 INFO [main] com.dianwoba.common.datasource.DataSourceAspect:invoke:32 restore database connection Exception in thread "main" java.lang.RuntimeException: my test
乘数正确,指数型增长,第1次延迟1s
第2次,上次延迟1s乘以乘数2=延迟2s
第3次,上次延迟2s乘以乘数2=延迟4s
…
指数增长,如果没有指定则为始终如一的固定间隔延迟类型。新版本已经增加了各种类型单独的属性配置的模板构建者:
RetryTemplate.builder() .maxAttempts(10) .exponentialBackoff(100, 2, 10000) .retryOn(IOException.class) .traversingCauses() .build(); RetryTemplate.builder() .fixedBackoff(10) .withinMillis(3000) .build(); RetryTemplate.builder() .infiniteRetry() .retryOn(IOException.class) .uniformRandomBackoff(1000, 3000) .build();
backoff.random
测试代码
@Component
public class MyTask {
private Long lastTime = null;
@Retryable( backoff = @Backoff( delay = 1000, multiplier = 2, random = true), maxAttempts = 10)
public void doExecute(){
if (lastTime == null) {
lastTime = System.currentTimeMillis();
}
System.out.println("## actual delay:" + (System.currentTimeMillis() - lastTime) );
RuntimeException runtimeException = new RuntimeException("my test");
throw runtimeException;
}
}
输出结果
## current Date:Sat Aug 29 22:53:10 CST 2020
## current Date:Sat Aug 29 22:53:11 CST 2020
## current Date:Sat Aug 29 22:53:14 CST 2020
## current Date:Sat Aug 29 22:53:20 CST 2020
## current Date:Sat Aug 29 22:53:29 CST 2020
## current Date:Sat Aug 29 22:53:51 CST 2020
## current Date:Sat Aug 29 22:54:41 CST 2020
## current Date:Sat Aug 29 22:55:25 CST 2020
## current Date:Sat Aug 29 22:56:11 CST 2020
## current Date:Sat Aug 29 22:57:01 CST 2020
2020-08-29 22:57:01,617 INFO [main] com.dianwoba.common.datasource.DataSourceAspect:invoke:32 restore database connection
Exception in thread "main" java.lang.RuntimeException: my test
延迟更加随机化,由于是最大延迟为之前延迟的乘数的倍数,所以看不出规律。它的使用场景是使延迟更加随机化
exceptionexpression
测试代码
@Component
public class MyTask {
private Long lastTime = null;
public boolean canRetry(RuntimeException runtimeException) {
System.out.println("canRetry:"+runtimeException.hashCode());
return true;
}
@Retryable(exceptionexpression = "#{@myTask.canRetry(#root)}", backoff = @Backoff(delay = 1000, multiplier = 2, random = true))
public void doExecute() {
if (lastTime == null) {
lastTime = System.currentTimeMillis();
}
System.out.println("## actual delay:" + (System.currentTimeMillis() - lastTime));
RuntimeException runtimeException = new RuntimeException("my test");
System.out.println("doExecute:"+runtimeException.hashCode());
throw runtimeException;
}
}
输出结果
## actual delay:0 doExecute:626562869 2020-08-29 23:50:49,905 DEBUG [main] com.dianwoba.common.datasource.DataSourceAspect:invoke:28 public boolean com.dianwoda.billing.settle.task.MyTask.canRetry(java.lang.RuntimeException) execute with datasource is master canRetry:626562869 2020-08-29 23:50:49,906 INFO [main] com.dianwoba.common.datasource.DataSourceAspect:invoke:32 restore database connection 2020-08-29 23:50:51,335 DEBUG [main] com.dianwoba.common.datasource.DataSourceAspect:invoke:28 public boolean com.dianwoda.billing.settle.task.MyTask.canRetry(java.lang.RuntimeException) execute with datasource is master canRetry:626562869 2020-08-29 23:50:51,336 INFO [main] com.dianwoba.common.datasource.DataSourceAspect:invoke:32 restore database connection ## actual delay:1450 doExecute:90418597 2020-08-29 23:50:51,337 DEBUG [main] com.dianwoba.common.datasource.DataSourceAspect:invoke:28 public boolean com.dianwoda.billing.settle.task.MyTask.canRetry(java.lang.RuntimeException) execute with datasource is master canRetry:90418597 2020-08-29 23:50:51,338 INFO [main] com.dianwoba.common.datasource.DataSourceAspect:invoke:32 restore database connection 2020-08-29 23:50:53,620 DEBUG [main] com.dianwoba.common.datasource.DataSourceAspect:invoke:28 public boolean com.dianwoda.billing.settle.task.MyTask.canRetry(java.lang.RuntimeException) execute with datasource is master canRetry:90418597 2020-08-29 23:50:53,620 INFO [main] com.dianwoba.common.datasource.DataSourceAspect:invoke:32 restore database connection ## actual delay:3734 doExecute:307531674 2020-08-29 23:50:53,621 INFO [main] com.dianwoba.common.datasource.DataSourceAspect:invoke:32 restore database connection Exception in thread "main" java.lang.RuntimeException: my test
注意:1.2.5之后表达式的预发有所改变,详情可以参考官方文档:https://github.com/spring-projects/spring-retry
以上这篇spring Retryable注解实现重试详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持考高分网。



