由于远程程序服务健壮性和网络的波动等因素,可能造成接口调用失败,因此有必要实现Client远程调用的重试机制
一、基于异常捕捉的重试机制:
public String getDetailFromClient(){ //重试次数 int retryCount = 3; //重试时长(单位:ms) int retryTimes = 5000; while (retryCount > 0) { log.info("重试次数{}", retryCount); try { //远程调用的服务 String result = httpClient.list(); //判断返回的数据是否为零 if (ObjectUtils.isEmpty(result)) { log.info("数据为空,开始重试,retryTimes:{}", retryTimes); //返回数据为零,进行重试 retryCount--; //重试时长间隔 Thread.sleep(retryTimes); continue; } // 返回非零数据,直接返回结果 return result; } catch (Exception e) { //超时异常:进行重试 retryCount--; try { //重试时长间隔 Thread.sleep(retryTimes); } catch (InterruptedException e1) { e1.printStackTrace(); } log.error("调用发生异常,开始重试,retryTimes:{},异常信息{}", retryTimes, e); } } // 重试次数用尽,返回空值 return "重试次数用尽,返回空值"; }
二、基于Spring-AOP切面的重试机制:
1、引入AOP依赖:
<!--AOP切面--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> <version>2.6.13</version> </dependency>
2、自定义重试注解:
import java.lang.annotation.*; @Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface RepeatableAnnotateBus { /** * 重试次数 * @return */ int repeatAmount() default 3; /** * 重试时间 * @return */ int repeatTime() default 1; }
3、重试机制切面:
import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; @Slf4j @Component @Aspect public class RepeatableAspectUtil { @Pointcut("@annotation(com.iven.aspect.RepeatableAnnotateBus)") public void cutRepeatableMethod() { } @Around("cutRepeatableMethod()") public Object repeat(ProceedingJoinPoint joinPoint) throws InterruptedException { // 获取重试次数和重试间隔 RepeatableAnnotateBus repeatableBus = ((MethodSignature) joinPoint.getSignature()) .getMethod().getAnnotation(RepeatableAnnotateBus.class); int amount = repeatableBus.repeatAmount(); int time = repeatableBus.repeatTime(); Throwable error = new RuntimeException(); for (int i = 1 ; i <= amount ; i++){ try { //joinpoint.proceed():用于执行目标对象的原本方法,也就是切入点 (join point) 所表示的方法。 //通过使用 proceed() 方法,可以在切面中实现方法拦截、日志记录等功能。 Object result = joinPoint.proceed(); if (ObjectUtils.isEmpty(result)) { log.info("数据为空,开始重试,retryTimes:{}", i * time * 10000L); //返回数据为零,进行重试, 重试时长间隔 Thread.sleep(i * time * 10000L); continue; } return result; } catch (Throwable throwable) { error = throwable; log.warn("调用发生异常,开始重试,retryTimes:{}", i * time * 10000L); } //重试时长间隔 Thread.sleep(i * time * 10000L); } log.error("重试次数耗尽,{}", error); return null; } }
4、相关使用:
@RepeatableAnnotateBus public String getDetailFromAspect(){ //远程调用服务 return httpClient.list(); }
三、参考:
标签:16,int,retryTimes,重试,Client,org,import,public From: https://www.cnblogs.com/Iven-L/p/17776660.html