当我们调用一个接口可能由于网络等原因造成第一次失败,再去尝试就成功了,这就是重试机制,spring支持重试机制,并且在Spring Cloud中可以与Hystaix结合使用,可以避免访问到已经不正常的实例。
写一个简单的demo,加入依赖:
org.springframework.boot spring-boot-starter-web org.springframework.retry spring-retry org.aspectj aspectjweaver
在主类上加上@EnableRetry
注解,表示启用重试机制。
@SpringBootApplication@EnableRetrypublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class,args); } }
定义一个简单的controller层:
@RestControllerpublic class HelloController { Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private PayService payService; @GetMapping("/createOrder") public String createOrder(@RequestParam int num) throws Exception{ int remainingnum = payService.minGoodsnum(num == 0 ? 1: num); logger.info("剩余的数量==="+remainingnum); return "库库存成功"; } }
在controller中调用减库存的service接口,
@Servicepublic class PayService { private Logger logger = LoggerFactory.getLogger(getClass()); private final int totalNum = 100000; @Retryable(value = Exception.class,maxAttempts = 3,backoff = @Backoff(delay = 2000,multiplier = 1.5)) public int minGoodsnum(int num) throws Exception{ logger.info("minGoodsnum开始"+ LocalTime.now()); if(num <= 0){ throw new Exception("数量不对"); } logger.info("minGoodsnum执行结束"); return totalNum - num; } }
在minGoodsnum方法上加上@Retryable
注解,value
值表示当哪些异常的时候触发重试,maxAttempts
表示最大重试次数默认为3,delay
表示重试的延迟时间,multiplier
表示上一次延时时间是这一次的倍数。
测试:
重试三次抛出异常。
使用@Recover
注解,当重试次数达到设置的次数的时候,还是失败抛出异常,执行的回调函数。
关于@Recover
注解
和minGoodsnum定义在一个类中
@Recoverpublic int recover(Exception e){ logger.warn("减库存失败!!!"); //记日志到数据库 return totalNum; }
重试测试一下,
感觉意义不大,重试失败的时候应该还是要抛出异常的,在上层进行catch记录日志,当然也有特殊的场景适用。