Spring-Retry

Spring-Retry

引入Maven依赖

 <dependency>
            <groupId>org.springframework.retrygroupId>
            <artifactId>spring-retryartifactId>
        dependency>
        <dependency>
            <groupId>org.aspectjgroupId>
            <artifactId>aspectjweaverartifactId>
        dependency>

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

@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
  • multiplier:重试时间间隔指数增长倍数
  • delayExpression:延时表达式
  • maxDelayExpression:最大延时表达式
  • multiplierExpression:增长表达式
  • random:附加随机事件,需要multiplier>0

@Recover

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

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

@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没有拦截到异常信息,所以也不会进行重试

你可能感兴趣的:(SpringBoot,spring,java,spring,boot)