Spring-retry 优雅的实现循环重试功能
引言
在实际的应用场景中,可能经常会遇到,当请求一个接口调一个服务的时候,出现异常或网络出现故障的情况下就会失败,而对于那些重要的服务当失败后,可能我们就会进行重试,多调用几次,如果还是失败再另外进行单独处理。接下来,就是要讲解的重点内容,我们可以通过@Retryable注解,优雅的实现循环重试功能。
1:引入依赖
<!-- spring-retry --> <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
2:在启动类上开启retry重试功能
package com.patent.cloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.retry.annotation.EnableRetry; @SpringBootApplication @EnableRetry public class PatenCloudApplication { public static void main(String[] args) { SpringApplication.run(PatenCloudApplication.class, args); } }
3:业务处理,在要调用的方法上加上@Retryable注解
@Autowired private VehicleLocationDataService vehicleLocationDataService; /** * 需要在启动类中添加@EnableRetry注释以开启重试功能,最后在相应的方法上添加@Retryable注解。 * @Recover注解,重试完成之后执行的回调方法 * 重试机制,如果调用方法过程中触发了RuntimeException异常,则20秒后重试一次,最多重试3次,三次重试后会触发recover方法 * @param orderNo * @param chassisNo * @param carStatus */ @GetMapping("/retryMyTest") @Retryable(value = RuntimeException.class,maxAttempts = 3, backoff = @Backoff(value = 10000L), recover = "recover", listeners = {"myRetryListener"}) public void retry(String orderNo, String chassisNo, String carStatus) throws RuntimeException { vehicleLocationDataService.retryMyTest(orderNo,chassisNo,carStatus); }
4:retryMyTest方法的逻辑处理
package com.patent.cloud.retry; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @Slf4j @Service public class VehicleLocationDataService { public static Integer retryCount = 1; public void retryMyTest(String orderNo, String chassisNo, String carStatus){ boolean flag = false; if("P8012985".equals(chassisNo)){ flag = true; } if(retryCount==4){ retryCount =1; } if(!flag){ log.info("有异常哦,我再试多几次看下还有没异常, 重试第{}次, {},{},{}",retryCount, orderNo,chassisNo,carStatus); retryCount ++; throw new RuntimeException("调用失败!"); } } }
当程序出现RuntimeException的时候,就好触发重试
5:recover方法,上边定义了maxAttempts 为3,也就是说,重试三次后,如果还失败了,则调用recover方法,需要在方法上标注@Recover注解
@Recover public void recover(RuntimeException runtimeException,String orderNo, String chassisNo, String carStatus) { log.info("=======触发重试了recover方法======{}==={}=={}===",orderNo,chassisNo,carStatus); }
6:监听,同时还是对重试方法进行了监听,如我们在方法retry上,加了listeners 监听
package com.patent.cloud.retry; import lombok.extern.slf4j.Slf4j; import org.springframework.retry.RetryCallback; import org.springframework.retry.RetryContext; import org.springframework.retry.listener.RetryListenerSupport; import org.springframework.stereotype.Service; @Slf4j @Service public class MyRetryListener extends RetryListenerSupport { @Override public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) { log.info("监听到重试过程关闭了"); log.info("======================================================================="); } @Override public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable) { log.info("监听到重试过程错误了"); } @Override public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) { log.info("======================================================================="); log.info("监听到重试过程开启了"); return true; } }
7:运行结果