场景:
某些场景下,如果接口出现异常需要进行重试,例如网络抖动、调用接口超时等并非接口代码导致的报错,此时可以进行接口重试机制
1、导入 spring retry 重试依赖
<!-- spring retry -->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
因为 spring retry 是基于 aop 实现的,所以还需要导入 aop 依赖
2、主启动类标注启动重试功能 @EnableRetry
3、测试重试方法
@Retryable(
value = Exception.class,
maxAttempts = 5,
backoff = @Backoff(delay = 1000, multiplier = 2),
recover = "recoverTestSpringRetryTwo"
)
@Override
public void testSpringRetry(String name, String address) throws BizException {
log.info("姓名:{},地址:{}", name, address);
//模拟报错
if (StrUtil.equals(name, "张三")) {
throw new BizException("出现异常");
}
}
参数说明:
【1】@Retryable:标注该方法出现异常,进行重试
【2】value:对哪种异常进行重试
【3】maxAttempts:最大重试次数,默认3
【4】backoff:重试策略,delay = 1000, multiplier = 2 延迟1秒(1000毫秒)进行第一次重试,后续每次延迟时间会以 multiplier 的倍数进行重试,示例为:1(1000毫秒)秒、2(1000*2)秒、4(2000*2)秒、8(4000*2)秒...以此类推进行重试
【5】recover:最大重试次数耗尽触发此方法。有多个异常回调方法时需要用此属性指定用哪个
【6】当重试次数耗尽依然抛出异常,可以通过 @Recover 方法进行失败回调、拿到参数进行手工处理
4、异常重试回调方法
使用 @Recover 标注重试回调方法
@Recover
public void recoverTestSpringRetryOne(Exception e, String name, String address) {
log.info("recoverTestSpringRetryOne异常重试回调方法开始执行,参数为:姓名:{},地址:{}", name, address);
log.info("此时可以把此参数记录到重试异常回调表中,以便后续通过定时任务调度补偿处理");
log.error("异常消息:{}", e.getMessage());
e.printStackTrace();
}
@Recover
public void recoverTestSpringRetryTwo(Exception e, String name, String address) {
log.info("recoverTestSpringRetryTwo异常重试回调方法开始执行,参数为:姓名:{},地址:{}", name, address);
log.info("此时可以把此参数记录到重试异常回调表中,以便后续通过定时任务调度补偿处理");
log.error("异常消息:{}", e.getMessage());
e.printStackTrace();
}
注意:
【1】@Recover 方法的返回类型必须与 @Retryable 方法的返回类型一致
【2】@Recover 方法的第一个参数必须是 Throwable 类型
【3】回调方法与重试方法必须在同一个实现类中
【4】如果一个实现类中有多个异常回调方法,在 @Retryable 中可以使用 recover 属性指定回调的方法名
5、验证结果:
c.h.m.m.t.s.impl.TestDailyServiceImpl :46 - 姓名:张三,地址:上海
c.h.m.m.t.s.impl.TestDailyServiceImpl :46 - 姓名:张三,地址:上海
c.h.m.m.t.s.impl.TestDailyServiceImpl :46 - 姓名:张三,地址:上海
c.h.m.m.t.s.impl.TestDailyServiceImpl :46 - 姓名:张三,地址:上海
c.h.m.m.t.s.impl.TestDailyServiceImpl :46 - 姓名:张三,地址:上海
c.h.m.m.t.s.impl.TestDailyServiceImpl :63 - recoverTestSpringRetryTwo异常重试回调方法开始执行,参数为:姓名:张三,地址:上海
c.h.m.m.t.s.impl.TestDailyServiceImpl :64 - 此时可以把此参数记录到重试异常回调表中,以便后续通过定时任务调度补偿处理
c.h.m.m.t.s.impl.TestDailyServiceImpl :65 - 异常消息:出现异常
BizException(code=null, message=出现异常)
at com.hkl.mpjoin.modules.testdaily.service.impl.TestDailyServiceImpl.testSpringRetry(TestDailyServiceImpl.java:49)
从结果可以看出,符合重试策略的预期,重试5次后依然异常失败,进入失败回调方法结束