一、SpringRetry
1、引入maven依赖
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
2、启动类,或配置类加注解@EnableRetry
3、在需要重试的方法上加注解
@Retryable(value = Exception.class, maxAttempts = 3,
backoff = @Backoff(delay = 5000L,multiplier = 2))
Retryable注解的方法在发生异常时会重试,参数说明:
value:当指定异常发生时会进行重试 ,HttpClientErrorException是RestClientException的子类。
include:和value一样,默认空。如果 exclude也为空时,所有异常都重试
exclude:指定异常不重试,默认空。如果 include也为空时,所有异常都重试
maxAttemps:最大重试次数,默认3
backoff:重试等待策略,默认空
@Backoff注解为重试等待的策略,参数说明:
delay:指定重试的延时时间,默认为1000毫秒
multiplier:指定延迟的倍数,比如设置delay=5000,multiplier=2时,第一次重试为5秒后,第二次为10(5x2)秒,第三次为20(10x2)秒。
4.重试失效场景
- 本类内部调用的方法不能使用
public class demo { public void A() { B(); } @Retryable(Exception.class) public void B() { throw new RuntimeException("retry..."); } }
- 使用@Retryable不能使用try catch捕获异常
二、RetryTemplate
在不适用SpringRetry的情况下使用
private RetryTemplate withRetry() {
RetryTemplate retryTemplate = new RetryTemplate();
//重试次数
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(3, Collections.singletonMap(Exception.class, true));
retryTemplate.setRetryPolicy(retryPolicy);
//固定时间重试机制
FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
fixedBackOffPolicy.setBackOffPeriod(5000);
retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
return retryTemplate;
}
try {
withRetry().execute(context -> {
//...
return null;
});
} catch (RuntimeException re) {
// ..
}
或配置类创建RetryTemplate
@Configuration
public class RetryTemplateConfiguration {
@Bean
public RetryTemplate retryTemplate() {
RetryTemplate retryTemplate = new RetryTemplate();
//重试次数
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(3);
retryTemplate.setRetryPolicy(retryPolicy);
//固定时间重试机制
FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
fixedBackOffPolicy.setBackOffPeriod(5000);
retryTemplate.setBackOffPolicy(fixedBackOffPolicy);
return retryTemplate;
}
}
retryTemplate.execute(context -> {
return this.push(array, finalReceiveAddr);
});
三、自己实现aop注解
1、注解定义
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Retry {
int num() default 3;
Class<? extends Exception>[] value() default {Exception.class};
}
2、切面方法
@Slf4j
@Aspect
@Component
@Order(Ordered.LOWEST_PRECEDENCE)
public class RetryAspect {
@Pointcut("@annotation(com.test.common.aop.Retry)")
public void retryAspect() {
}
@Around("retryAspect()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
Retry retry = method.getDeclaredAnnotation(Retry.class);
try {
return joinPoint.proceed(joinPoint.getArgs());
} catch (Exception e) {
Exception exception = e;
for (int i = 0; i < retry.num(); i++) {
log.warn("执行失败,进入第{}次重试", i + 1);
for (Class cls : retry.value()) {
if (!cls.isInstance(exception)) {
continue;
}
try {
return joinPoint.proceed(joinPoint.getArgs());
} catch (Exception e1) {
exception = e1;
}
}
}
throw e;
}
}
}