spring-retry

简介: spring-retry使用说明

## Spring-Retry


**引入Maven依赖**


```xml

<dependency>

           <groupId>org.springframework.retry</groupId>

           <artifactId>spring-retry</artifactId>

       </dependency>

       <dependency>

           <groupId>org.aspectj</groupId>

           <artifactId>aspectjweaver</artifactId>

       </dependency>

```


使用`@EnableRetry`注解开启重试机制


```java

@SpringBootApplication

@EnableRetry

public class Application {

   public static void main(String[] args) {

       SpringApplication.run(Application.class,args);

   }

}

```


> **@Retryable说明**

>

> * recover:用于重试失败的兜底策略,一般不使用这个属性

> * interceptor:忽略

> * value:支持重试的异常,与include等价,如果value和include都不配置则重试所有

> * include:需要重试的异常

> * exclude:不重试的异常

> * label:重试处的唯一名词定义,不定义则会基于方法签名生成,一般用不到

> * stateful:是否有状态的重试(需要学习spring-retry 有状态重试相关,一般用不到)

> * maxAttempts:最大执行次数

> * maxAttemptsExpression:忽略

> * backoff:重试策略

> * listeners:spring-retry监听器配置,此处配置的是监听器在ioc容器中的id,需要了解spring retry的监听器才会使用


> **Backoff说明**

>

> * value:与delay效果等价,失败后等待多少ms重试下一次

> * delay:与value效果等价,失败后等待多少ms重试下一次

> * maxDelay:重试等待的最大时间,如果maxDelay<delay,则maxDelay默认为30000ms

> * multiplier:重试时间间隔指数增长倍数

> * delayExpression:延时表达式

> * maxDelayExpression:最大延时表达式

> * multiplierExpression:增长表达式

> * random:附加随机事件,需要multiplier>0


**@Recover**


一个方法如果需要recover策略,只需要在同类中加入一个方法,方法使用recover标记即可


注意:方法的第一个参数为异常类型,后面为原方法的参数


```java

@Recover

public void defaultFallback(Exception e){

   //do it

}

```


**测试**


注解:@Retryable


效果:默认重试3次,下次重试延时1s


```

2023-04-13 10:34:36.277  INFO 16704 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request 2...

2023-04-13 10:34:37.289  INFO 16704 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request 2...

2023-04-13 10:34:38.296  INFO 16704 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request 2...

```


注解:@Retryable(maxAttempts = 7,include = {Exception.class},backoff = @Backoff(delay = 1000,maxDelay = 10000))


效果:重试7次,延时在1000ms-10000ms之间


```

2023-04-13 10:36:38.484  INFO 6024 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request3 ...

2023-04-13 10:36:41.342  INFO 6024 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request3 ...

2023-04-13 10:36:44.318  INFO 6024 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request3 ...

2023-04-13 10:36:48.794  INFO 6024 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request3 ...

2023-04-13 10:36:50.264  INFO 6024 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request3 ...

2023-04-13 10:36:59.808  INFO 6024 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request3 ...

2023-04-13 10:37:01.882  INFO 6024 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request3 ...

```


注解:@Retryable(maxAttempts = 5,include = {Exception.class},backoff = @Backoff(delay = 1000,multiplier = 2))


效果:重试5次,第一次延时为1000ms,之后为第一次的2倍


```

2023-04-13 10:39:11.654  INFO 5692 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request4 ...

2023-04-13 10:39:12.665  INFO 5692 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request4 ...

2023-04-13 10:39:14.667  INFO 5692 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request4 ...

2023-04-13 10:39:18.672  INFO 5692 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request4 ...

2023-04-13 10:39:26.673  INFO 5692 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request4 ...

```


注解:@Retryable(maxAttempts = 5,backoff = @Backoff(value = 1500,maxDelay = 10000,multiplier = 3))


效果:最大重试5次,第一次延时1500ms,之后为前一次延时时长3倍,时长大于10000ms时,则按10000ms计算


```

2023-04-13 10:41:43.491  INFO 13928 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request5 ...

2023-04-13 10:41:45.005  INFO 13928 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request5 ...

2023-04-13 10:41:49.510  INFO 13928 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request5 ...

2023-04-13 10:41:59.523  INFO 13928 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request5 ...

2023-04-13 10:42:09.525  INFO 13928 --- [           main] c.v.service.impl.HttpRestServiceImpl     : do request5 ...

```


**失效场景**


因为spring-retry采用的时aspectj动态代理,所以也会出现一些类似于spring事务的失效场景


例如


* 在同一service中a方法调用b方法,b方法上标有`@Retryable`注解,那么在运行期间a方法调用b方法时相当于this.b(),而此时的this指向的是原本被代理的对象,所以会导致注解失效

* 在service中主动try-catch方法中的异常,导致aop没有拦截到异常信息,所以也不会进行重试

相关文章
|
Java 容器 Spring
|
4月前
|
安全 Java 开发者
Spring系列一
Spring系列一
|
8月前
|
存储 消息中间件 Java
深入理解Spring的TransactionSynchronizationManager
深入理解Spring的TransactionSynchronizationManager
655 0
|
缓存 Java 数据库连接
|
9月前
|
Java 测试技术 数据库连接
Spring常见知识总结
Spring常见知识总结
37 2
|
9月前
|
Java 程序员 Maven
|
Java 应用服务中间件 程序员
spring
spring
84 0
|
Java 数据库连接 Spring
|
druid Java 关系型数据库
😧 Spring_day02 ✅(一)
😧 Spring_day02 ✅
82 0
😧 Spring_day02 ✅(一)
|
存储 Java Maven
😧 Spring_day01 ✅(二)
😧 Spring_day01 ✅
79 0