Spring之Spring Retry重试机制

目录

  • 一、概念
  • 二、注解介绍
    • 1、@EnableRetry
    • 2、@Retryable参数介绍
      • (1)value
      • (2)exclude
      • (3)maxAttempts
      • (4)backoff
      • (5)delay
      • (6)multiplier
      • (7)maxDelay
    • 3、@Recover回调函数

一、概念

Srping提供了失败重试功能Spring Retry,在网络不稳定的情况下,避免调用外部接口失败导致流程中断。也可以结合SpringCloudHystrix熔断一起使用。Spring Retry提供了自定义重试、回调等等。

二、注解介绍

1、@EnableRetry

SpringBoot项目想要使用Spring Retry需要在启动类Application上面加此注解

/**
 * @author chengyanqi
 * @date 2020/7/12 21:35
 */
@EnableRetry
@SpringBootApplication
@ComponentScan(basePackages = "com.chengyanqi")
@EnableAutoConfiguration
public class MySpringBootApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(MySpringBootApplication.class, args);
    }
}

2、@Retryable参数介绍

@Retryable注解可以加在方法上,也可以加在类上。加在类上时,此类中所有方法均有失败重试机制。

参数 说明
value 指定需要触发重试机制的异常
exclude 和value一样,默认空,当exclude也为空时,所有异常都重试
maxAttempts 重试次数,默认3,第一次执行也算在总次数中
backoff 重试补偿机制,默认没有
delay 每次重试等待的时间,毫秒
maxDelay 最大延迟的时间,不设置默认为30秒钟。
multiplier 重新发起延迟时间的基数。比如delay=100L,mutiplier=2,第一次重试延迟100ms,第二次重试延迟200ms,第三次400ms

(1)value

  • 指定需要触发重试机制的异常
@Retryable(value = ClassNotFoundException.class, backoff = @Backoff(delay = 100L, multiplier = 2, maxDelay = 5000L))
public void retryTest() throws Exception {
     System.out.println(count++);
     throw new RuntimeException();
}
1
结束class java.lang.RuntimeException

value设置为ClassNotFoundException,抛出RuntimeException,没有进行重试。

@Retryable(value = RuntimeException.class, backoff = @Backoff(delay = 100L, multiplier = 2, maxDelay = 5000L))
public void retryTest() throws Exception {
    System.out.println(++count);
    throw new RuntimeException();
}
1
2
3
结束class java.lang.RuntimeException

value=RuntimeException.class,抛出RuntimeException。正常重新调用。

(2)exclude

  • exclude|和value一样,默认空,当exclude也为空时,所有异常都重试
@Retryable(value = Exception.class, exclude = RuntimeException.class,backoff = @Backoff(delay = 100L, multiplier = 2, maxDelay = 5000L))
public void retryTest() throws Exception {
    System.out.println(++count);
    throw new RuntimeException();
}
1
结束class java.lang.RuntimeException

设置value为Exception所有异常。exclude为RuntimeException,抛出异常时,没有方法只执行了一次,没有进行重试

(3)maxAttempts

  • maxAttemps|重试次数,默认3,第一次执行也算在总次数中
@Retryable(value = Exception.class,backoff = @Backoff(delay = 100L, multiplier = 2, maxDelay = 5000L))
public void retryTest() throws Exception {
    System.out.println(++count);
    throw new RuntimeException();
}
1
2
3
结束class java.lang.RuntimeException

maxAttemps为空,默认执行三次。修改为2再次执行。

@Retryable(value = Exception.class, maxAttempts = 2, backoff = @Backoff(delay = 100L, multiplier = 2, maxDelay = 5000L))
public void retryTest() throws Exception {
    System.out.println(++count);
    throw new RuntimeException();
}
1
2
结束class java.lang.RuntimeException

(4)backoff

  • 重试补偿机制,默认没有
  • @Backoff可以自定义补偿,参数有:delay,multiplier,maxDelay

(5)delay

  • 每次重试等待的时间,毫秒
@Retryable(value = Exception.class, backoff = @Backoff(delay = 100L, multiplier = 1, maxDelay = 5000L))
public void retryTest() throws Exception {
    SimpleDateFormat format = new SimpleDateFormat("ss秒SSS毫秒");
    System.out.println("第"+ ++count +"次执行,时间:" +format.format(new Date()));
    throw new RuntimeException();
}
第1次执行,时间:13秒111毫秒
第2次执行,时间:13秒212毫秒
第3次执行,时间:13秒312毫秒
结束class java.lang.RuntimeException

设置delay为100L,每隔100ms执行一次方法一次

(6)multiplier

  • 重新发起延迟时间的基数。比如delay=100L,mutiplier=2,第一次重试延迟100ms,第二次重试200ms。
@Retryable(value = Exception.class,maxAttempts=5, backoff = @Backoff(delay = 100L, multiplier = 3, maxDelay = 5000L))
public void retryTest() throws Exception {
    SimpleDateFormat format = new SimpleDateFormat("ss秒SSS毫秒");
    System.out.println("第"+ ++count +"次执行,时间:" +format.format(new Date()));
    throw new RuntimeException();
}
第1次执行,时间:51秒596毫秒
第2次执行,时间:51秒697毫秒
第3次执行,时间:51秒998毫秒
第4次执行,时间:52秒898毫秒
第5次执行,时间:55秒598毫秒
结束class java.lang.RuntimeException

根据运行结果可以看出,multiplier设置为3,每次重试的次数为3的倍数×delay。
第一次100,第二次300,第三次900,第四次2700…

(7)maxDelay

  • 最大延迟的时间,不设置默认为30秒钟。
@Retryable(value = Exception.class,maxAttempts=10, backoff = @Backoff(delay = 100L, multiplier = 2, maxDelay = 300L))
public void retryTest() throws Exception {
    SimpleDateFormat format = new SimpleDateFormat("ss秒SSS毫秒");
    System.out.println("第"+ ++count +"次执行,时间:" +format.format(new Date()));
    throw new RuntimeException();
}
第1次执行,时间:32秒094毫秒
第2次执行,时间:32秒195毫秒
第3次执行,时间:32秒395毫秒
第4次执行,时间:32秒695毫秒
第5次执行,时间:32秒996毫秒
第6次执行,时间:33秒296毫秒
第7次执行,时间:33秒596毫秒
第8次执行,时间:33秒897毫秒
第9次执行,时间:34秒197毫秒
第10次执行,时间:34秒497毫秒
结束class java.lang.RuntimeException

执行次数设置为10,倍数设置为2,等待时间为100ms。当我们设置maxDelay=300L时,可以从执行结果看出,每次重调时间间隔最大为300ms。

3、@Recover回调函数

  • 当重试到达指定次数时,被注解的方法将被回调,可以在该方法中进行日志处理。需要注意的是发生的异常和入参类型一致时才会回调。
  • (注意,需跟重处理方法在同一个类中)
@Retryable(value = Exception.class,maxAttempts=3, backoff = @Backoff(delay = 100L, multiplier = 2, maxDelay = 300L))
public void retryTest() throws Exception {
    SimpleDateFormat format = new SimpleDateFormat("ss秒SSS毫秒");
    System.out.println("第" + ++count + "次执行,时间:" + format.format(new Date()));
    throw new RuntimeException("自定义异常");
}
@Recover
public void recover(RuntimeException e) {
    System.out.println("触发回调函数:" + e.getMessage());
}
第1次执行,时间:09秒230毫秒
第2次执行,时间:09秒332毫秒
第3次执行,时间:09秒532毫秒
触发回调函数:自定义异常

这是模拟异常场景,如果业务代码正常运行,不会执行@Recover的代码。下面模拟正常调用场景。

@Retryable(value = Exception.class,maxAttempts=3, backoff = @Backoff(delay = 100L, multiplier = 2, maxDelay = 300L))
public void retryTest() throws Exception {
    SimpleDateFormat format = new SimpleDateFormat("ss秒SSS毫秒");
    System.out.println("第" + ++count + "次执行,时间:" + format.format(new Date()));
    if (count > 2)
        return;
    throw new RuntimeException("自定义异常");
}
@Recover
public void recover(RuntimeException e) {
    System.out.println("触发回调函数:" + e.getMessage());
}
第1次执行,时间:22秒634毫秒
第2次执行,时间:22秒735毫秒
第3次执行,时间:22秒936毫秒

你可能感兴趣的:(spring)