由于网络不稳定或网络抖动经常会造成接口请求失败的情况,当我们再去尝试就成功了,这就是重试机制。
本文首发于Java潘老师个人博客:SpringBoot整合spring-retry组件实现重试机制
其主要目的就是要尽可能地提高请求成功的概率,但一般情况下,我们请求第一次失败,代码运行就抛出异常结束了,如果想再次请求可能还需要手工操作,这非常地不方便,可行性也不佳。因此,Spring框架提供了对重试机制支持,并且在Spring Cloud中可以与Hystrix结合使用,可以避免访问到已经不正常的实例。
重试机制要素如下:
对于非幂等性的方法我们要慎用重试机制,可能会造成意料之外的后果。
所谓幂等性:就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。
下面我们就来看下,我们应该如何使用SpringBoot来整合spring-retry组件实现重试机制。
首先我们在SpringBoot项目中的pom.xml添加相关依赖,如下:
<!-- 重试相关依赖包 --> <dependency>     <groupId>org.springframework.retry</groupId>     <artifactId>spring-retry</artifactId>     <version>1.2.4.RELEASE</version> </dependency>   <dependency>     <groupId>org.aspectj</groupId>     <artifactId>aspectjweaver</artifactId>     <version>1.9.4</version> </dependency> 在主启动类Application上添加@EnableRetry注解,实现对重试机制的支持
@SpringBootApplication @EnableRetry public class RetryApplication {       public static void main(String[] args) {           SpringApplication.run(RetryApplication.class, args);     }   } 注意:@EnableRetry也可以使用在配置类、ServiceImpl类、方法上
我们针对需要实现重试的方法上添加@Retryable注解,使该方法可以实现重试,这里我列出ServiceImpl中的一个方法:
@Service public class RetryServiceImpl implements RetryService {       @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000,multiplier = 1.5))     public String testRetry() throws Exception {           System.out.println("开始执行代码:"+ LocalTime.now());         int code = 0;         // 模拟一直失败         if(code == 0){            // 这里可以使自定义异常,@Retryable中value需与其一致             throw new Exception("代码执行异常");         }         System.out.println("代码执行成功");         return "success";     } } 说明:@Retryable配置元数据情况:
 value :针对指定抛出的异常类型,进行重试,这里指定的是Exception
 maxAttempts :配置最大重试次数,这里配置为3次(包含第一次和最后一次)
 delay: 第一次重试延迟间隔,这里配置的是2s
 multiplier :每次重试时间间隔是前一次几倍,这里是1.5倍
@RestController @RequestMapping("/test") public class TestController {     @Autowired     private RetryService retryService;       @GetMapping("/retry")     public String testRetry() throws Exception {         return retryService.testRetry();     } } 发送请求后,我们发现后台打印情况,确实重试了3次,并且在最后一次重试失败的情况下,才抛出异常,具体如下(可以注意下时间间隔):

一般情况下,我们重试最大设置的次数后,仍然失败抛出异常,我们会通过全局异常处理类进行统一处理,但是我们其实也可以自行处理,可以通过@Recover注解来实现,具体如下:
@Service public class RetryServiceImpl implements RetryService {       @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000,multiplier = 1.5))     public String testRetry() throws Exception {           System.out.println("开始执行代码:"+ LocalTime.now());         int code = 0;         if(code == 0){             // 这里可以使自定义异常,@Retryable中value需与其一致             throw new Exception("代码执行异常");         }         System.out.println("代码执行成功");         return "success";     }       /**      * 最终重试失败处理      * @param e      * @return      */     @Recover     public String recover(Exception e){           System.out.println("代码执行重试后依旧失败");         return "fail";     } } 注意:
 1)@Recover的方法中的参数异常类型需要与重试方法中一致
 2)该方法的返回值类型与重试方法保持一致
 再次测试如下(发现不会再抛出异常):

本文首发于Java潘老师个人博客:SpringBoot整合spring-retry组件实现重试机制