Spring Boot使用Retry机制实现失败重试

2022-09-04 13:48:55

在实际应用过程中,我们时常会遇到需要重试的机制。例如发送短信的时候,发送失败一次后需要再次发起第二次或者第三次重试,常规的思路就是记录当前短信对应的发送失败次数,当小于三次且均为失败时就发起请求。这里我们介绍一种极为方便的重试机制,springboot下整合retry。

一. 使用场景

发送短信请求,若失败则需要再次发起请求,若一直失败则需要满足达到了两次重试请求。

若不引入任何重试机制,我们的实现逻辑大体如下,记录短信唯一标识以及对应的请求历史和请求结果,若失败则累加失败次数,直到某一次成功了,或者重试次数达到了三次。

这里我们需要引入数据库来记录失败次数,以及增加数据库请求,有没有一种更方便的方式来实现呢,答案是有的。

二. Retry机制

这里我们以SpringBoot为例:

  • 首先我们引入相关pom依赖

    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId></dependency></dependencies>
  • 在启动类上加上注解@EnableRetry

    @SpringBootApplication@EnableRetrypublicclassApplication{publicstaticvoidmain(String[] args){SpringApplication.run(Application.class,args);}}
  • 定义Controller层:这里我们把下层异常进行throws抛出,或者我们进行try,catch;否则重试机制将会不生效。

    @RestControllerpublicclassHelloController{Logger logger=LoggerFactory.getLogger(getClass());@AutowiredprivateSmsService smsService;@GetMapping("/sendSms")publicvoidsendSms(@RequestParamString phoneNumber,@RequestParamString content)throwsException{boolean isSuccess= smsService.sendSms(phoneNumber, content);if(isSuccess){
            	logger.info("短信发送成功");}else{
                logger.error("短信发送失败");}}}
  • 定义Service

    @ServicepublicclassSmsService{privateLogger logger=LoggerFactory.getLogger(getClass());@Retryable(value=Exception.class,maxAttempts=3,backoff=@Backoff(delay=2000,multiplier=1.5))publicbooleansendSms(String phoneNumber,String content)throwsException{// 模拟短信发送失败thrownewException("短信发送失败");}}
  • 解释@Retryable注解

    value:表示遇到何种异常情况下需要重试

    maxAttempts:表示最大重试次数

    delay:表示重试的延迟时间(毫秒计数)

    multiplier:表示上一次延迟时间为本次的倍数

以上就是我们实现的简单重试机制示例,相较于记录失败次数并发起重试,这种方式是不是简单又优雅,第一次看到这种实现方法的时候笔者也被惊艳到了,若在实际业务开发过程中需要使用重试机制,我们可以借鉴该种实现思路。

三. 拓展

若在@Retryable设置的最大重试次数下,还是没有成功,我们需要回调另一个方法,那我们该如何实现。

这里我们引入@Recover注解。

我们在sendSms的Service类中,加上以下代码:

@Recoverpublicvoidrecover(Exception e){
        logger.warn("发送短信失败!!!");//记日志到数据库}

我们再进行测试,就会发现,当我们达到最大重试3次后,若还是失败则会执行该代码块。

参考资料:

  • 作者:Vainycos
  • 原文链接:https://blog.csdn.net/imVainiycos/article/details/123106451
    更新时间:2022-09-04 13:48:55