java实现重试机制
为什么提到重试机制
之前我们的系统调用第三方影像平台接口,下载文件,但是远程程序服务健壮性和网络的波动等因素,可能造成接口调用失败。
重试实现方案
- spring aop方式
- spring-retry
- guava-retry
spring aop实现重试机制
引入AOP的包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
自定义注解
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RepeatableBus {
/**
* 重试次数
* @return
*/
int repeatAmount() default 3;
/**
* 重试时间
* @return
*/
int repeatTime() default 1;
}
切面类
@Slf4j
@Component
@Aspect
public class RepeatableAspect {
@Pointcut("@annotation(com.sunpeiyu.demoitem.repeatable.RepeatableBus)")
public void cutRepeatableMethod() {
}
@Around("cutRepeatableMethod()")
public Object repeat(ProceedingJoinPoint joinPoint) throws InterruptedException {
// 获取重试次数和重试间隔
RepeatableBus repeatableBus = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(RepeatableBus.class);
int amount = repeatableBus.repeatAmount();
int time = repeatableBus.repeatTime();
Throwable error = new RuntimeException();
for (int i = 1 ; i <= amount ; i++){
try {
Object result = joinPoint.proceed();
return result;
} catch (Throwable throwable) {
error = throwable;
log.warn("调用发生异常,开始重试,retryTimes:{}", time);
}
Thread.sleep(time * 1000L);
}
throw new RuntimeException("重试次数耗尽", error);
}
}
测试
@RepeatableBus(repeatAmount = 3, repeatTime = 1)
public void testRepeat() {
log.info("===================> 执行了方法RedisService.testRepeat");
Object obj = null;
obj.toString();
}
spring-retry
导包
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
开启spring-retry
@EnableRetry
使用spring-retry
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 2000, multiplier = 2))
public void testRepeat() {
log.info("===================> 执行了方法RedisService.testRepeat");
Object obj = null;
obj.toString();
}
@Recover
public void recover(RuntimeException e) {
log.error("++++++++++++++++++++++ 达到最大重试次数", e);
}
测试
解释
@EnableRetry : 开启重试机制
@Retryable : 重试注解,其中maxAttempts为最大重试次数,delay为延时时长,multiplier为延时时长增长的倍数
@Recover : 达到最大重试次数执行的方法
注意
- 调用的方法和被调用的方法不能在同一个类中,因为spring-retry也是通过spring aop实现的,在同一个类中,aop无法进行切面处理。
- @recover注解的方法不能有返回值,否则无法执行。