解決FeignClient重試機(jī)制造成的接口冪等性
FeignClient重試機(jī)制造成的接口冪等性
Feign源碼分析,其實現(xiàn)類在 SynchronousMethodHandler,實現(xiàn)方法是public Object invoke(Object[] argv) ,它的代碼分析如下:
1.構(gòu)造請求數(shù)據(jù),將對象轉(zhuǎn)換為json:
RequestTemplate template = buildTemplateFromArgs.create(argv);
2.發(fā)送請求進(jìn)行執(zhí)行(執(zhí)行成功會解碼響應(yīng)數(shù)據(jù)):
executeAndDecode(template, options);
3. 執(zhí)行請求會有重試機(jī)制:
Retryer retryer = this.retryer.clone();
while (true) {
try {
return executeAndDecode(template, options);
} catch (RetryableException e) {
try {
retryer.continueOrPropagate(e);
} catch (RetryableException th) {
Throwable cause = th.getCause();
// 重試結(jié)束 或則 不允許重試,則通過拋異常的形式終止
if (propagationPolicy == UNWRAP && cause != null) {
throw cause;
} else {
throw th;
}
}
if (logLevel != Logger.Level.NONE) {
logger.logRetry(metadata.configKey(), logLevel);
}
continue;
}
}
4. Retryer是重試器,其實現(xiàn)方法有兩種
第一種是系統(tǒng)默認(rèn)實現(xiàn)方式,第二種是可以自定義重試器,一般少用,通過默認(rèn)實現(xiàn)重試類Default可以看到其構(gòu)造函數(shù)中的重試次數(shù)為5。
public Default() {
this(100, SECONDS.toMillis(1), 5);
}
public Default(long period, long maxPeriod, int maxAttempts) {
this.period = period;
this.maxPeriod = maxPeriod;
this.maxAttempts = maxAttempts;
this.attempt = 1;
}
因此解決Feign調(diào)用的冪等性問題最簡單也就最常用的就是讓Feign不重試。
為FeignClient增加請求重試機(jī)制
spring cloud通過feign client進(jìn)行服務(wù)之間調(diào)用的時候,默認(rèn)不會進(jìn)行重試,這樣會有一個問題,比如你的服務(wù)在滾動升級重啟的時候,feign的調(diào)用將直接失敗,但其實我是滾動重啟,重啟了一個服務(wù)實例,還有另外一個服務(wù)實例是可用的,應(yīng)該允許自動均衡策略重試請求發(fā)送到另外一個可用的服務(wù)實例上去。
要啟用重試機(jī)制,首先必須引入spring-retry依賴:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
然后通過注冊一個bean:
/**
*
* 注冊一個重試Bean
* 默認(rèn)FeignClient不會進(jìn)行重試,使用的是{@link feign.Retryer#NEVER_RETRY}
*
* @see FeignClientsConfiguration#feignRetryer()
*/
@Bean
public Retryer feignRetryer() {
return new Retryer.Default();
}
大功告成。
不過還有個前提就是,你的遠(yuǎn)程調(diào)用接口方法的必須是冪等的(比如GET方法認(rèn)為是冪等的,調(diào)用多少次結(jié)果都一樣,而POST方法有可能有重復(fù)提交問題),不然還是不會重試的,因為其他HttpMethod被認(rèn)為是非冪等的,不能重復(fù)執(zhí)行,因此不能被重試
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
mybatis中關(guān)于type-aliases-package的使用
這篇文章主要介紹了mybatis中關(guān)于type-aliases-package的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
MyBatis使用級聯(lián)操作解決lombok構(gòu)造方法識別失敗問題
這篇文章主要介紹了MyBatis使用級聯(lián)操作解決lombok構(gòu)造方法識別失敗問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07
Java實現(xiàn)多級表頭和復(fù)雜表頭的導(dǎo)出功能
這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)多級表頭和復(fù)雜表頭的導(dǎo)出功能的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
Mybatis-plus操作json字段實戰(zhàn)教程
這篇文章主要介紹了Mybatis-plus操作json字段實戰(zhàn)教程,本文結(jié)合實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-02-02

