SpringBoot进阶教程(八十四)spring-retry

在日常的一些场景中, 很多需要进行重试的操作.而spring-retry是spring提供的一个基于spring的重试框架,某些场景需要对一些异常情况下的方法进行重试就会用到spring-retry。spring-retry可以帮助我们以标准方式处理任何特定操作的重试。在spring-retry中,所有配置都是基于简单注释的。

v添加引用

复制代码
        <dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

v启用@Retryable

复制代码
@SpringBootApplication
@EnableRetry
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }

}

要使用@EnabelRetry开启重试才行,声明在配置类或者启动类上都可以激活。

v在方法上添加@Retryable

创建service接口

复制代码
public interface HomeService {
    int convertStatus(int status) throws Exception;
}

在service实现类并添加@Retryable

复制代码
@Slf4j
@Service
public class HomeServiceImpl implements HomeService {
    /**
     * value:抛出指定异常才会重试
     * include:和value一样,默认为空,当exclude也为空时,默认所有异常
     * exclude:指定不处理的异常
     * maxAttempts:最大重试次数,默认3次(包括第一次调用)
     * backoff:重试等待策略,
     * 默认使用@Backoff,@Backoff的value默认为1000L,我们设置为2000; 以毫秒为单位的延迟(默认 1000);delay:重试的间隔时间,就是value
     * multiplier delay时间的间隔倍数,默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒。
     * @param status
     * @return
     * @throws Exception
     */
    @Override
    @Retryable(retryFor = Exception.class,maxAttempts = 3,backoff = @Backoff(delay = 2000,multiplier = 1.5))
    public int convertStatus(int status) throws Exception{
        System.out.println("进入convertStatus时间:"+ LocalTime.now());
        if (status < 0){
            throw new Exception("状态小于0是非法的");
        }

        System.out.println("convertStatus: status++");

        return status++;
    }

    /**
     * Spring-Retry还提供了@Recover注解,用于@Retryable重试失败后处理方法。
     * 如果不需要回调方法,可以直接不写回调方法,那么实现的效果是,重试次数完了后,如果还是没成功没符合业务判断,就抛出异常。
     * @Recover标记方法必须要与@Retryable注解的方法"形参"保持一致,第一入参为要重试的异常(一定要是@Retryable方法里抛出的异常或者异常父类),其他参数与@Retryable保持一致,返回值也要一样,否则无法执行!
     *
     * @param e
     * @param status @Retryable注解的原方法参数,可以保留,也可以不要。
     * @return
     */
    @Recover
    public int recover(Exception e, int status) {
        //记日志到数据库 或者调用其余的方法
        System.out.println(String.format("兜底方法执行,异常信息:%s,status:%d", e.toString(), status));
        return -1;
    }
}

@Retryable修饰的convertStatus()方法,如果调用期间报了异常,那么它将进行重试3次(默认三次),如果超过最大重试次数,则执行@Retryable修饰的recover()方法,
创建controller

复制代码
@Slf4j
@RestController
public class HomeController {
    @Autowired
    HomeService homeService;

    @GetMapping("convertStatus")
    public ReturnValue<?> convertStatus(@RequestParam("token") String token,
                                        @RequestParam("status") int status) throws Exception {
        int result = homeService.convertStatus(status);
        return ReturnValue.buildSuccessResult(result);
    }
}

验证效果

v常用注解介绍

@EnableRetry

启用重试,开启aop的功能,默认使用jdk的动态代理。proxyTargetClass属性为true时(默认false),使用CGLIB代理
@Retryable

标记当前方法会使用重试机制。

|-------------|-----------|------------|-------------------------------------------------|
| 属性 | 类型 | 默认值 | 说明 |
| interceptor | String | "" | 将interceptor的bean名称应用到retryable(),和其他的属性互斥 |
| include | Class[] | {} | 哪些异常可以触发重试 ,默认为空 |
| exclude | Class[] | {} | 哪些异常将不会触发重试,默认为空,如果和include属性同时为空,则所有的异常都将会触发重试 |
| value | Class[] | {} | 可重试的异常类型 |
| label | String | "" | 统计报告的唯---标签。如果没有提供,调用者可以选择忽略它,或者提供默认值 |
| maxAttempts | int | 3 | 尝试的最大次数(包括第一次失败),默认为3次 |
| backoff | @Backoff | @Backoff() | @Backoff @Backoff()指定用于重试此操作的backoff属性。默认为 |

@Backoff

重试回退策略(立即重试还是等待一会再重试)

|------------|---------|---------|---------------------------------|
| 属性 | 类型 | 默认值 | 说明 |
| delay | long | 0 | 如果不设置则默认使用1000 ms等待重试,和value同义词 |
| maxDelay | long | 0 | 最大重试等待时间 |
| multiplier | long | 0 | 用于计算下一个延迟延迟的乘数(大于0生效) |
| random | boolean | FALSE | 随机重试等待时间 |

@Backoff 的参数会影响我们使用哪种退避策略

  • FixedBackOffPolicy
    默认退避策略,每 1 秒重试 1 次
  • ExponentialBackOffPolicy
    指数退避策略,当设置 multiplier 时使用,每次重试时间间隔为 当前延迟时间 * multiplier。
  • ExponentialRandomBackOffPolicy
    指数随机退避策略。在指数退避策略的基础上增加了随机性。具体策略查看 getSleepAndIncrement() 方法
  • UniformRandomBackOffPolicy
    均匀随机策略,设置 maxDely 但没有设置 multiplier 时使用,重试间隔会在 maxDelay 和 delay 间随机

@Recover

作为恢复处理程序的方法调用的注释。重试方法最终会调用标注了@Recover 的方法。

@Recover声明的方法和@Retryable 方法相同类型的返回值,Throwable 第一个参数是可选的(但是,如果没有其他参数匹配,则不带该参数的方法将被调用)。从失败方法的参数列表中依次填充后续参数。

v注意事项

  • 使用了Spring-Retry是通过捕获异常的方式来触发重试的,@Retryable注解的方法直接实例化调用不会触发重试,要先将实现类实例化到Spring容器中,然后通过注入等方式使用
  • Spring-Retry是通过捕获异常的方式来触发重试的,@Retryable标注方法产生的异常不能使用try-catch捕获,要在方法上抛出异常,不然不会触发重试
  • recover方法的返回值必须与Spring-Retry是通过捕获异常的方式来触发重试的,@Retryable方法一致
  • 查询可以进行重试,写操作要慎重,除非业务方支持重入

v源码地址

https://github.com/toutouge/javademosecond/tree/master/hellolearn

作  者:请叫我头头哥

出  处:http://www.cnblogs.com/toutou/

关于作者:专注于基础平台的项目开发。如有问题或建议,请多多赐教!

版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信

声援博主:如果您觉得文章对您有帮助,可以点击文章右下角**【推荐】** 一下。您的鼓励是作者坚持原创和持续写作的最大动力!

相关推荐
带刺的坐椅1 天前
SpringBoot3 使用 SolonMCP 开发 MCP
java·ai·springboot·solon·mcp
LUCIAZZZ2 天前
JVM之虚拟机运行
java·jvm·spring·操作系统·springboot
堕落年代2 天前
SpringSecurity当中的CSRF防范详解
前端·springboot·csrf
一零贰肆2 天前
深入理解SpringBoot中的SpringCache缓存技术
java·springboot·springcache·缓存技术
LUCIAZZZ4 天前
JVM之内存管理(一)
java·jvm·spring·操作系统·springboot
LUCIAZZZ6 天前
JVM之内存管理(二)
java·jvm·后端·spring·操作系统·springboot
天上掉下来个程小白7 天前
缓存套餐-01.Spring Cache入门案例
java·redis·spring·缓存·springboot·springcache
程序员buddha8 天前
SpringBoot+Dubbo+Zookeeper实现分布式系统步骤
分布式·zookeeper·dubbo·springboot
天上掉下来个程小白9 天前
缓存套餐-03.功能测试
redis·缓存·springboot·苍穹外卖·springcache
Ten peaches9 天前
苍穹外卖(订单状态定时处理、来单提醒和客户催单)
java·数据库·sql·springboot