Feign调用可重试的最佳方案分享
作者:JAVA旭阳 时间:2021-06-09 12:19:23
前言
在我们公司里,不同的服务之间通过Feign
进行远程调用,但是,我们在尝试使调用可重试时遇到了一个小问题,Feign
框架本身可以配置的自己的重试机制,但是它是一刀切的方式,所有的调用都是同样的机制,没有办法像我们希望的那样在每个方法的基础上配置。不过我在项目中探索除了一种新的写法,通过spring-retry
框架集合Feign
去实现重试机制,可以为每个调用实现不同的重试机制,那究竟是如何做到的呢,继续往下看呀。
自定义注解@FeignRetry
为了解决上面提到的问题,让Feign调用的每个接口单独配置不同的重试机制。我们使用了面向切面编程并编写了一个自定义注解:@FeignRetry
。此注释的工作方式类似于@Retryable
的包装器,并与其共享相同的规范以避免混淆。
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface FeignRetry {
Backoff backoff() default @Backoff();
int maxAttempt() default 3;
Class<? extends Throwable>[] include() default {};
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Backoff {
long delay() default 1000L;;
long maxDelay() default 0L;
double multiplier() default 0.0D;;
}
FeignRetryAspect
切面处理@FeignRetry
注解。
Slf4j
@Aspect
@Component
public class FeignRetryAspect {
@Around("@annotation(FeignRetry)")
public Object retry(ProceedingJoinPoint joinPoint) throws Throwable {
Method method = getCurrentMethod(joinPoint);
FeignRetry feignRetry = method.getAnnotation(FeignRetry.class);
RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.setBackOffPolicy(prepareBackOffPolicy(feignRetry));
retryTemplate.setRetryPolicy(prepareSimpleRetryPolicy(feignRetry));
// 重试
return retryTemplate.execute(arg0 -> {
int retryCount = arg0.getRetryCount();
log.info("Sending request method: {}, max attempt: {}, delay: {}, retryCount: {}",
method.getName(),
feignRetry.maxAttempt(),
feignRetry.backoff().delay(),
retryCount
);
return joinPoint.proceed(joinPoint.getArgs());
});
}
private BackOffPolicy prepareBackOffPolicy(FeignRetry feignRetry) {
if (feignRetry.backoff().multiplier() != 0) {
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(feignRetry.backoff().delay());
backOffPolicy.setMaxInterval(feignRetry.backoff().maxDelay());
backOffPolicy.setMultiplier(feignRetry.backoff().multiplier());
return backOffPolicy;
} else {
FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
fixedBackOffPolicy.setBackOffPeriod(feignRetry.backoff().delay());
return fixedBackOffPolicy;
}
}
private SimpleRetryPolicy prepareSimpleRetryPolicy(FeignRetry feignRetry) {
Map<Class<? extends Throwable>, Boolean> policyMap = new HashMap<>();
policyMap.put(RetryableException.class, true); // Connection refused or time out
policyMap.put(ClientException.class, true); // Load balance does not available (cause of RunTimeException)
if (feignRetry.include().length != 0) {
for (Class<? extends Throwable> t : feignRetry.include()) {
policyMap.put(t, true);
}
}
return new SimpleRetryPolicy(feignRetry.maxAttempt(), policyMap, true);
}
private Method getCurrentMethod(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
return signature.getMethod();
}
}
捕获FeignRetry
注解的方法,将配置传递给Spring RetryTemplate
,根据配置调用服务。
@FeignRetry 的使用
用法很简单,只需将注释放在我们希望重试机制处于活动状态的 Feign Client
方法上即可。自定义切面的用法类似于Spring自带的@Retryable
注解。
@GetMapping
@FeignRetry(maxAttempt = 3, backoff = @Backoff(delay = 500L))
ResponseEntity<String> retrieve1();
@GetMapping
@FeignRetry(maxAttempt = 6, backoff = @Backoff(delay = 500L, maxDelay = 20000L, multiplier = 4))
ResponseEntity<String> retrieve2();
另外还需要在应用程序类中使用 @EnableRetry
注释来启动重试,比如可以加载SpringBoot的启动类中。
来源:https://juejin.cn/post/7187252990821007397
标签:Feign,调用,可重试
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
Java实现FIFO任务调度队列策略
2021-09-19 09:05:37
![](https://img.aspxhome.com/file/2023/7/75787_0s.jpg)
java内部类的定义与分类示例详解
2022-07-01 20:16:47
剖析Java中线程编程的概念
2022-02-02 04:12:51
![](https://img.aspxhome.com/file/2023/7/77967_0s.jpg)
简单谈谈Java 中的线程的几种状态
2023-05-10 13:29:45
java异常处理执行顺序详解try catch finally
2022-10-01 04:10:10
![](https://img.aspxhome.com/file/2023/2/62122_0s.png)
使用Maven搭建Hadoop开发环境
2021-09-11 07:55:45
对Java ArrayList的自动扩容机制示例讲解
2022-04-09 07:58:25
Unity的IPostprocessBuild实用案例深入解析
2023-05-29 05:54:49
小米Java程序员第二轮面试10个问题 你是否会被刷掉?
2023-11-13 09:00:29
![](https://img.aspxhome.com/file/2023/6/59026_0s.jpg)
Spring @Conditional通过条件控制bean注册过程
2023-08-06 10:00:11
Unity实现跑马灯抽奖效果
2022-10-09 04:09:54
![](https://img.aspxhome.com/file/2023/4/67054_0s.jpg)
FasfDFS整合Java实现文件上传下载功能实例详解
2022-05-27 02:30:46
![](https://img.aspxhome.com/file/2023/8/70268_0s.png)
浅谈Spring Boot 开发REST接口最佳实践
2021-10-08 12:24:35
![](https://img.aspxhome.com/file/2023/0/62420_0s.png)
基于ReentrantLock的实现原理讲解
2023-11-23 22:43:23
![](https://img.aspxhome.com/file/2023/9/59849_0s.jpg)
C#超市收银系统设计
2023-06-21 00:00:09
![](https://img.aspxhome.com/file/2023/9/66579_0s.png)
Java SpringBoot拦截器详解
2021-11-01 15:29:37
![](https://img.aspxhome.com/file/2023/7/77067_0s.gif)
SparkSQL开窗函数分析使用示例
2022-04-16 02:26:32
关于idea中SpringBoot启动失败的坑
2022-07-18 13:02:24
![](https://img.aspxhome.com/file/2023/4/62234_0s.png)
C#中using指令的几种用法
2022-01-25 01:35:25
Java8中的LocalDateTime你会使用了吗
2023-11-15 07:02:07