Feign調(diào)用可重試的最佳方案分享
前言
在我們公司里,不同的服務之間通過Feign
進行遠程調(diào)用,但是,我們在嘗試使調(diào)用可重試時遇到了一個小問題,Feign
框架本身可以配置的自己的重試機制,但是它是一刀切的方式,所有的調(diào)用都是同樣的機制,沒有辦法像我們希望的那樣在每個方法的基礎上配置。不過我在項目中探索除了一種新的寫法,通過spring-retry
框架集合Feign
去實現(xiàn)重試機制,可以為每個調(diào)用實現(xiàn)不同的重試機制,那究竟是如何做到的呢,繼續(xù)往下看呀。
自定義注解@FeignRetry
為了解決上面提到的問題,讓Feign調(diào)用的每個接口單獨配置不同的重試機制。我們使用了面向切面編程并編寫了一個自定義注解:@FeignRetry
。此注釋的工作方式類似于@Retryable
的包裝器,并與其共享相同的規(guī)范以避免混淆。
@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
,根據(jù)配置調(diào)用服務。
@FeignRetry 的使用
用法很簡單,只需將注釋放在我們希望重試機制處于活動狀態(tài)的 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的啟動類中。
總結
Feign
重試其實是一個很常見的場景,我們本文通過了自定義了一個@FeignRetry
注解來實現(xiàn)可重試的機制,針對不同的Feign
接口還可以使用不同的重試策略,是不是很方便,快在你的項目中用起來吧。
到此這篇關于Feign調(diào)用可重試的最佳方案分享的文章就介紹到這了,更多相關Feign調(diào)用可重試內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Kotlin基礎教程之控制流(順序,分支,循環(huán))
這篇文章主要介紹了Kotlin基礎教程之控制流的相關資料,需要的朋友可以參考下2017-05-05SpringCloud+Tornado基于jwt實現(xiàn)請求安全校驗功能
這篇文章主要介紹了SpringCloud+Tornado基于jwt實現(xiàn)請求安全校驗,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12SpringBoot+Redis隊列實現(xiàn)Java版秒殺的示例代碼
本文主要介紹了SpringBoot+Redis隊列實現(xiàn)Java版秒殺的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-06-06如何自定義Mybatis-Plus分布式ID生成器(解決ID長度超過JavaScript整數(shù)安全范圍問題)
MyBatis-Plus默認生成的是 64bit 長整型,而 JS 的 Number 類型精度最高只有 53bit,這篇文章主要介紹了如何自定義Mybatis-Plus分布式ID生成器(解決ID長度超過JavaScript整數(shù)安全范圍問題),需要的朋友可以參考下2024-08-08