一、背景
- 调用第三方接口,按照最大次数轮询去获取结果,或因为网络波动导致超时等。
- Retry重试框架,支持AOP切入的方式使用,支持注解;重试次数、重试延迟、重试触发条件、重试的回调方法等功能来实现重试机制
二、整合Retry
2.1 pom文件加入依赖
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency>
2.2 容器启动类上添加注解@EnableRetry
@EnableRetry @SpringBootApplication public class ParamApplication { public static void main(String[] args) { SpringApplication.run(ParamApplication.class, args); } }
2.3 支付服务类PayService,获取剩余数量
@Slf4j @Service public class PayService { private final static int TOTAL_NUM = 100000; @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 5000L, multiplier = 2)) public int getRemainingAmount(int num) throws Exception { log.info("getRemainingAmount======" + LocalTime.now()); if (num <= 0) { throw new Exception("数量不对"); } log.info("getRemainingAmount======执行结束"); return TOTAL_NUM - num; } }
@Retryable:标记当前方法使用重试机制
value:触发重试机制的条件,当遇到Exception时,会重试
maxAttempts :设置最大重试次数,默认为3次
delay:重试延迟时间,单位毫秒,即距离上一次重试方法的间隔
multiplier:delay重试延迟时间的间隔倍数,即第一次为5秒,第二次为5乘以2为10秒,依此类推
三、测试
创建controller类
@Slf4j @RestController @RequestMapping("/retry") public class RetryController { @Resource private PayService payService; @PostMapping("/test") public String retryTest(@RequestParam int num) throws Exception { int remainingnum = payService.getRemainingAmount(num); log.info("剩余数量===" + remainingnum); return "success"; } }
postman调用
可以看到,第一次用时5S,第二次用时10S,第三次用时15S;
最后会抛出异常,可以在上层代码进行try-catch处理相关业务逻辑;
也可以写回调方法处理,在PayService类中添加如下代码,@Recover:当重试方法发生异常时,会执行该回调方法
@Recover public int recover(Exception e) { // 回调方法,业务逻辑处理 return -1; }
再次执行时,结果如下