spring boot下接口调用失败重试方案

背景:

在项目开发中,有时候会出现接口调用失败,本身调用又是异步的,如果是因为一些网络问题请求超时,总想可以重试几次把任务处理掉。

一些RPC框架,比如dubbo都是有重试机制的,但是并不是每一个项目多会使用dubbo框架,常规的小项目有时候直接使用http进行不同项目之间的交互。

个人想法:

使用spring aop和自定义注解来,建立一套重试机制。

根据切入点和自定义注解,来完成重试工作。

exps:

定义一个注解:

 1 import org.springframework.stereotype.Component;
 2 
 3 import java.lang.annotation.Documented;
 4         import java.lang.annotation.ElementType;
 5         import java.lang.annotation.Retention;
 6         import java.lang.annotation.RetentionPolicy;
 7         import java.lang.annotation.Target;
 8 
 9 @Retention(RetentionPolicy.RUNTIME)
10 @Target(ElementType.METHOD)
11 @Documented
12 @Component
13 public @interface RetryProcess {
14  //重试的次数
15  int value() default 1;
16 }
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicInteger;

@Aspect
@Component
public class AspectExceptionInterceptor {
    private  final Logger logger = LoggerFactory.getLogger(this.getClass());
    @AfterThrowing(pointcut=("execution(* com.tom.plus.ctl..*(..)) && @annotation(com.tom.plus.compent.RetryProcess)"))
    public void tryAgain(JoinPoint point) {
        logger.info("------------开始重试------------");
        try {
            Object object = point.getTarget();
            Field field = object.getClass().getDeclaredField("threadLocal");
            field.setAccessible(true);
            ThreadLocal<AtomicInteger> threadLocal = (ThreadLocal<AtomicInteger>) field.get(object);
            MethodSignature methodSignature = (MethodSignature) point.getSignature();
            RetryProcess retryProcess = methodSignature.getMethod().getAnnotation(RetryProcess.class);
            if (threadLocal.get().intValue() < retryProcess.value()) {
               int index = threadLocal.get().incrementAndGet();
                logger.info("开始重试第"+index);
                MethodInvocationProceedingJoinPoint methodPoint = ((MethodInvocationProceedingJoinPoint) point);
                methodPoint.proceed();
            }
        } catch (Throwable throwable) {
            //logger.error("重试失败",throwable);
            tryAgain(point);
        }
    }
}

测试代码:

@RetryProcess(value = 2)
@RequestMapping("/hero")
@ResponseBody
public String doIt2() {
//该接口会抛出异常,启动进行重试机制
testService.doProcess();
return "success";
}

原文地址:https://www.cnblogs.com/tom-plus/p/7844228.html