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();
}

image

spring-retry

导包

<dependency>
	<groupId>org.springframework.retry</groupId>
	<artifactId>spring-retry</artifactId>
</dependency>

开启spring-retry

@EnableRetry

image

使用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);
}

测试

image

解释

@EnableRetry : 开启重试机制
@Retryable : 重试注解,其中maxAttempts为最大重试次数,delay为延时时长,multiplier为延时时长增长的倍数
@Recover : 达到最大重试次数执行的方法

注意

  • 调用的方法和被调用的方法不能在同一个类中,因为spring-retry也是通过spring aop实现的,在同一个类中,aop无法进行切面处理。
  • @recover注解的方法不能有返回值,否则无法执行。
posted @ 2023-08-19 19:05  sunpeiyu  阅读(244)  评论(0编辑  收藏  举报