精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Feign的超時時間如何設置呢?

jf_ro2CN3Fa ? 來源:三友的java日記 ? 2023-11-15 10:22 ? 次閱讀

今天來聊一聊前段時間看到的一個面試題,也是在實際項目中需要考慮的一個問題,Feign 的超時時間如何設置?

Feign 的超時時間設置方式并不固定,它取決于 Feign 在項目中是如何使用的,不同的使用方式,超時時間設置方式也不大相同,甚至還可能有坑。

前置知識

由于文章會涉及到 Feign 的底層知識,如果不懂點 Feign 的基本概念的話,后面就看不下去了。

所以為了方便不了解 Feign 的小伙伴也能夠讀得懂文章,這里我就簡單地說說 Feign 的原理,點到為止,雖然不深入,但足夠應付這篇文章了。

Feign 的作用

在項目中,我們經常需要調用第三方提供的 Http 接口,此時我們就可以使用一些 Http 框架來實現,比如 HttpClient。

publicclassHttpClientDemo{

publicstaticvoidmain(String[]args)throwsException{
//創建一個HttpClient
HttpClienthttpClient=HttpClientBuilder.create().build();

//構建一個get請求
HttpGethttpGet=newHttpGet("http://192.168.100.1:8080/order/1");

//發送請求,獲取響應
HttpResponsehttpResponse=httpClient.execute(httpGet);
HttpEntityhttpEntity=httpResponse.getEntity();

//讀出響應值
Stringresponse=EntityUtils.toString(httpEntity);

System.out.println("Response:"+response);
}

}

如果項目中只有一兩個這種第三方接口這樣寫還行,但是一旦這種三方接口過多的話,每次都得這樣組裝參數,發送請求,寫一堆同樣的代碼,就顯然很麻煩了。

所以為了簡化發送 Http 請求的開發,減少重復代碼,Feign 就出現了。

Feign 是一個聲明式的 Http 框架

當你需要調用 Http 接口時,你需要聲明一個接口,加一些注解就可以了。而像組裝參數、發送 Http 請求等重復性的工作都交給 Feign 來完成。

Feign 的原理

雖然有了接口,但是僅僅有接口是不夠的,因為接口又不能創建對象,我們得需要對象。

Feign 為了方便我們為接口創建對象,提供的 Feign.Builder 這個內部類。

8d711d92-82d4-11ee-939d-92fbcf53809c.png

這個類的作用就是解析接口的上的注解,為接口生成一個動態代理對象,后面通過這個代理對象就可以發送請求了。

這個內部類有很多屬性,這些屬性都是 Feign 的核心組件。

在這些核心的組件中有一個叫 Client 的,上圖中我圈出來了。

8da0279a-82d4-11ee-939d-92fbcf53809c.png

這個 Client 類劃個重點,非常非常重要,本文討論的東西跟他有密切關系。

它只有一個方法 Response execute (Request request, Options options)

方法的第一個參數 Request 就是封裝了 http 請求的 url、請求方法,請求頭、請求體之類的參數。

8db7c242-82d4-11ee-939d-92fbcf53809c.png

第二個參數 Options 就是本文的主題,封裝了超時時間。

8dcc3a2e-82d4-11ee-939d-92fbcf53809c.png

返回值 Response就是封裝了一些響應碼 status、響應頭之類的。

8ddfaed8-82d4-11ee-939d-92fbcf53809c.png

所以通過方法的參數和返回值也可以猜出來,這個 Client 作用是用來組裝 HTTP 請求參數,發送 HTTP 請求的。并且 HTTP 請求超時時間是根據傳給 Client 的 Options 參數來決定的。

8df27d92-82d4-11ee-939d-92fbcf53809c.png

Feign 單獨使用時超時時間設置

Feign 本身就是一個 HTTP 客戶端,可獨立使用,Feign 提供了兩種超時時間設置方式。

1、通過 Feign.Builder 設置

前面提到,Feign.Builder 的作用是為接口的動態代理對象的。

Feign.Builder 里面有很多屬性,其中就有關于超時時間的屬性 Options。

8e04ed10-82d4-11ee-939d-92fbcf53809c.png

如果你不設置,那么超時時間就是默認的。

8e0f6c36-82d4-11ee-939d-92fbcf53809c.png

默認的就是連接超時 10s,讀超時 60s。

所以可以通過設置 Feign.Builder 中的 options 來設置超時時間。

來個 demo

環境準備,就是一個簡單的 SpringBoot 項目,引入一個 Feign 的依賴。

這里演示的是 Feign 原生的使用方式,脫離于 SpringCloud 環境,所以 Spring 的那些 @GetMappring 就不支持了,改用 Feign 本身提供的注解。

測試代碼

這里面的請求路徑都是不存在的,因為我們只關心傳給 Client 的 Options 參數值。

Client 在我們不設置的時候,就用默認的實現 Client.Default。

8e208a48-82d4-11ee-939d-92fbcf53809c.png

斷點打到 execute 方法的實現,運行,走起。

8e39bab8-82d4-11ee-939d-92fbcf53809c.png

結果就是我們設置的 5s。

2、在接口方法參數設置

除了在通過 Feign.Builder 時設置之外,Feign 還支持在接口的方法參數上設置。

此時你只需要在接口的方法上加一個 Options 類型的參數。

@RequestLine("GET/user/{userId}")
UserqueryUser(@Param("userId")IntegeruserId,Request.Optionsoptions);

這樣在傳參數時就可以設置超時時間了。

Useruser=client.queryUser(123,newRequest.Options(3,TimeUnit.SECONDS,3,TimeUnit.SECONDS,true));

同樣地,debug 就可以看見我們設置的 3s 了。

8e4f74d4-82d4-11ee-939d-92fbcf53809c.png

這兩種設置超時時間的主要區別就是方法參數設置超時時間的優先級高于 Feign.Builder 設置的超時時間。

用一張圖來總結一下上面的關系。

8e6506be-82d4-11ee-939d-92fbcf53809c.png

所以,如果你單獨使用 Feign 的時候,你就可以通過如上的兩種方式來設置超時時間。

SpringCloud 下 Feign 單獨使用超時時間設置

在 SpringCloud 環境下,只是對 Feign 進行了一層包裝,所以即使沒有 Ribbon 和注冊中心,Feign 也是可以單獨使用的,但是用法有點變化

注解都換成 SpringMVC 的注解

接口上需要加 @FeignClient 注解

用 @EnableFeignClients 掃描這些接口

不過,默認情況下 Feign 還是需要結合 Ribbon 來使用的。

如果你只想單獨使用 Feign,那么就設置一下 @FeignClient 注解的 url 屬性,指定請求的地址和端口就可以了。

8e78f232-82d4-11ee-939d-92fbcf53809c.png

所以,既然只是包裝,前面提到的兩種方式設置超時時間當然可以繼續使用:

通過 Feign.Builder

通過接口的方法參數

方法參數設置形式跟前面提到的一模一樣,但是通過 Feign.Builder 來設置卻不太一樣。

由于 SpringCloud 會自己創建 Feign.Builder,不需要我們創建,所以在設置 Options 時,Spring 提供了兩種快捷方式來設置。不過最終還是設置到 Feign.Builder 中。

1、聲明一個 Options Bean

Spring 在構建 Feign.Builder 的時,會從容器中查找 Options 這個 Bean,然后設置到 Feign.Builder 中。

@Configuration
publicclassFeignConfiguration{

@Bean
publicRequest.Optionsoptions(){
returnnewRequest.Options(8,TimeUnit.SECONDS,8,TimeUnit.SECONDS,true);
}

}

此時 debug 就可以看到設置到 Feign.Builder 的代碼。

8e98cd64-82d4-11ee-939d-92fbcf53809c.png

這段代碼在 FeignClientFactoryBean 中的 configureUsingConfiguration 方法中.

2、配置文件中設置

除了聲明 Bean 之外,Spring 還提供了通過配置文件的方式配置,如下:

同樣地,debug 就可以看見。

8ebb1dec-82d4-11ee-939d-92fbcf53809c.png

這段代碼在 FeignClientFactoryBean 中的 configureUsingConfiguration 方法中。

2、配置文件中設置

除了聲明 Bean 之外,Spring 還提供了通過配置文件的方式配置,如下:

feign:
client:
config:
default:
connectTimeout:10000
readTimeout:10000

同樣地,debug 就可以看見。

這段代碼在 FeignClientFactoryBean 中的 configureUsingConfiguration 方法中。

聲明 Bean 和配置文件都可以設置,那么同時設置哪種優先級高呢?

如無特殊配置,遵守 SpringBoot 本身的配置規定

約定 > 配置 > 編碼

所以基于這個規定,配置文件的配置優先級大于手動聲明 Bean 的優先級。

到這,我們又學到了兩種 Spring 為了方便我們設置 Feign.Builder 提供的配置方式:

聲明 Options Bean

配置文件

把他們倆加到前面畫的圖中:

8ed7c9f6-82d4-11ee-939d-92fbcf53809c.png

所以,如果你使用了 SpringCloud 提供的方式來使用 Feign,那么就可以通過聲明 OptionsBean 和配置文件的方式更加方便地來設置超時時間。

最終其實還是通過 Feign.Builder 來設置的。

SpringCloud 下通過 Ribbon 來設置

當 Feign 配合 Ribbon 使用時,除了上面兩種方式之外,還可以通過 Ribbon 來設置超時時間。

但是這里我不知道你會不會好奇:

Ribbon 不是負載均衡組件,怎么可以設置超時時間?

跟 Ribbon 的定位有關,除了負載均衡組件之外,Ribbon 也干發送 HTTP 請求的事,也就是不配合 Feign,他照樣可以發送 HTTP 請求。

來個簡單 demo

8eee0c34-82d4-11ee-939d-92fbcf53809c.png

解釋一下上面的代碼意思:

第一步,設置 user 服務的兩個服務實例地址;

第二步,獲取 user 服務對應的 RestClient,這 RestClient 就可以用來發送 HTTP 請求;

第三步,構建一個 HTTP 請求;

第四步,就是發送 HTTP 請求,以負載均衡的方式。

這樣,此時就會從兩個服務實例中根據負載均衡選取一個服務地址發送 HTTP 請求,Ribbon 既然可以發送 HTTP 請求,那么自然而然就可以設置超時時間

Feign 在整合 Ribbon 的時候,為了統一配置,就默認將自己的超時時間交由 Ribbon 管理

所以,在默認情況下,Feign 的超時時間可以由 Ribbon 配置。而 Ribbon 默認連接和讀超時時間只有 1s,所以在默認情況下,Feign 的超時時間只有 1s。

8f10323c-82d4-11ee-939d-92fbcf53809c.png

IClientConfig 是 Ribbon 的配置類,Ribbon 所有的配置都可以從 IClientConfig 中獲取。

所以,在默認情況下,很容易就發生超時,不過我們可以通過配置文件修改即可。

ribbon:
ConnectTimeout:5000
ReadTimeout:5000

你知道你發現沒,上面說通過 Ribbon 設置 Feign 的超時時間,一直提到前面一直提到這個詞“默認”。

什么情況下叫默認呢?

所謂的默認,就是當你不主動設置 Feign 的超時時間的時候,就是默認。

換句話說,一旦你通過上面說的那些配置方式設置 Feign 的超時時間,就不是默認了

此時通過 Ribbon 設置的超時時間就不會生效了。

Feign 是如何在默認情況下將超時時間交給 Ribbon 管理的?

要想回答這個問題,就得先搬出前面反復提到的 Client 接口了。

在 SpringCloud 的環境下,有一個 Client 的實現,叫 LoadBalancerFeignClient。

8f1509ce-82d4-11ee-939d-92fbcf53809c.png

通過名字就可以看出,帶有負載均衡的 Client 實現,負載均衡的實現肯定是交給 Ribbon 來實現的。

所以,當 Feign 配合 Ribbon 時用的就是這個 Client 實現。

既然實現了 Client 接口,那就看看 execute 方法的實現邏輯。

8f24c01c-82d4-11ee-939d-92fbcf53809c.png

圖中 getClientConfig 方法就是判斷使用 Feign 或者 Ribbon 配置的核心邏輯。

核心的判斷邏輯就是這一行:

options==DEFAULT_OPTIONS

DEFAULT_OPTIONS 就是一個超時時間的常量。

8f56d156-82d4-11ee-939d-92fbcf53809c.png

當上述判斷條件成立時,就會通過 this.clientFactory.getClientConfig(clientName) (clientName) 獲取到 Ribbon 配置。

由于這是 Ribbon 的邏輯,這里就不深扒了,知道是這個意思就行。

當條件不成立時,用 Options 構建一個 FeignOptionsClientConfig。

8f7993e4-82d4-11ee-939d-92fbcf53809c.png

FeignOptionsClientConfig 就是簡單地將 Options 配置讀出來,設置到父類 DefaultClientConfigImpl 超時時間配置上。

DefaultClientConfigImpl 就算你不知道是什么也無所謂,你能看出的一件事就是,超時時間用的是傳遞給 Client 的 Options 參數。

所以,綜上,我們的問題就變得非常 easy 了,那就是什么時候。

options==DEFAULT_OPTIONS

只有當這個條件成立時,才使用 Ribbon 的配置。

這里我們先來捋一捋前面提到的東西。

前面我們反復提到,Client 的 Options 最終只來自于兩種配置:

Feign.Builder

方法參數

所以 DEFAULT_OPTIONS 這個 Options 一定是通過上面兩種方法中的其中一種設置的。

而方法參數是不可能設置的成 DEFAULT_OPTIONS。

因為這是我們控制的,只要我們參數不傳 DEFAULT_OPTIONS,那么永遠都不可能是 DEFAULT_OPTIONS。

此時只剩下一種情況,那就是 Spring 在構建在 Feign.Builder 的時候,設置成 DEFAULT_OPTIONS。

通過查找 DEFAULT_OPTIONS 的使用,我們可以追蹤到這么一段代碼。

8f84c480-82d4-11ee-939d-92fbcf53809c.png

這不就是前面提到的通過聲明 Bean 的方式來設置超時時間。

不同的是它加了 @ConditionalOnMissingBean,這個注解就是說,一旦我們自己沒有聲明 Options,就用他這個 Options。

到這終于真像大白了。

我們不設置超時時間,Spring 就會給 Feign.Builder 加一個 DEFAULT_OPTIONS 這個 Options。

在執行的時候,發現是 DEFAULT_OPTIONS,說明我們沒有主動設置過超是時間,就會使用 Ribbon 的超時時間。

為了方便理清上面的邏輯,這里整一張圖。

8f94bcc8-82d4-11ee-939d-92fbcf53809c.png

雖然 Feign 可以使用 Ribbon 的超時時間,但是 Ribbon 的配置的優先級是最最低的。

方法參數 > Feign 配置文件 > 聲明 Options > Ribbon 配置

Feign or Ribbon 配置用哪個好?

其實我個人更傾向于使用 Ribbon 的配置方式。

因為 Ribbon 除了可以設置超時時間之外,還可以配置重試機制、負載均衡等其它的配置

為了簡化和統一管理配置,使用 Ribbon 來配置超時時間。

可能你會有疑問,Feign 也支持重試機制,為什么不選擇 Feign?

這是因為 Feign 重試機制沒有 Ribbon 的好。

Ribbon 重試的時候會換一個服務實例來重試,因為原來出錯的可能不可用。

而 Feign 并不會換一個服務實例重試,他并不知道上一次使用的是哪個服務實例,這就導致可能會出現在一個不可用的服務實例上多次重試的情況。

引入 Hystrix 時超時時間設置

如果你之前的確沒有研究過關于 Feign 超時時間的配置關系,那么此時你應該有所收獲了。

但是這就結束了么?

不,事情沒那么簡單。

如果你的項目中使用了 Hystrix,那么就得小心前面說的那些配置了。

由于 Hystrix 跟 Feign 畢竟是一家人,所以當引入 Hystrix 時,Feign 就跟之前不一樣了。

Hystrix 會去干一件事,那就是給每個 Feign 的 HTTP 接口保護起來,畢竟 Hystrix 就是干保鏢這個事的。

但是這沒保護還好,一保護問題就不自覺地出現了。

Hystrix 在保護的時候,一旦發現被保護的接口執行的時間超過 Hystrix 設置的最大時間,就直接進行降級操作。

怎么降級的,這里咱不關心,咱關心的是這個 Hystrix 超時的最大值是多少。

因為一旦這個時間小于 Feign 的超時時間,那么就會出現 Http 接口正在執行,也沒有異常,僅僅是因為執行時間長,就被降級了。

而 Hystrix 的默認的超時時間的最大值就只有 1s。

8fb15982-82d4-11ee-939d-92fbcf53809c.png

所以就算你 Feign 超時時間設置的再大,超過 1s 就算超時,然后被降級,太坑了……

所以我們需要修改這個默認的超時時間的最大值,具體的配置項如下:

hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds:30000

并且時間上大致要符合下面這個原則:

Hystrix 超時時間 >= (連接超時時間 + 讀超時時間) * 重試次數

重試次數我們前面也提到了,雖然一般我們不設置,但是為了嚴謹還是得加上,因為一次 Http 接口的執行時間肯定跟重試次數有關,重試次數越多,時間就越長。

而連接超時時間 + 讀超時時間設置方式,前面提到很多次,不論是通過 Feign 本身設置還是通過 Ribbon 來設置,都是可以的。

總結

今天給大家扒了扒在不同使用條件下 Feign 的超時時間設置,總結起來大致如下:

單獨使用 Feign 時:通過 Feign.Builder 和方法參數;

SpringCloud 環境下單獨使用 Feign:方法參數、配置文件、聲明 Options Bean;

跟 Ribbon 配合使用:通過 Ribbon 的超時參數設置;

跟 Hystrix 配合使用:修改默認的超時時間,盡量符合 Hystrix 超時時間 >= (連接超時時間 + 讀超時時間) * 重試次數。







審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • URL
    URL
    +關注

    關注

    0

    文章

    139

    瀏覽量

    15313
  • 負載均衡
    +關注

    關注

    0

    文章

    106

    瀏覽量

    12360
  • HTTP接口
    +關注

    關注

    0

    文章

    21

    瀏覽量

    1777

原文標題:Feign 如何設置超時時間,不同情況下還真不一樣

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    ESP32-S2如何設置socket recv的超時時間

    請教一下: 如何設置socket recv的超時時間? 參考的是TCP server例程,有其它的提供超時的例程嗎? 謝謝!
    發表于 06-21 07:27

    請問lwIP連接超時時間如何設置

    目前的狀態:使用connect連接到服務端,如果服務端掉線需要等待大概20s才會返回連接錯誤,時間有點長,沒看到connect有設置超時的功能,有沒有什么方法設置連接
    發表于 09-27 09:44

    從機indication接收超時時間怎么更改?

    從機向主機indication消息后,主機會回復一個cfm事件,當主機沒有回復時,從機會超時一個超時事件,這個超時事件測試為30s,覺得有點長,當一直找不到哪里可以更改這個超時時間的,
    發表于 03-09 10:00

    如何去配置IWDG的超時時間

    IWDG是什么?IWDG有哪些功能?怎么去使用IWDG?如何去配置IWDG的超時時間
    發表于 08-02 10:04

    如何設置WWDG窗口看門狗的超時時間

    窗口看門狗WWDG的主要功能有哪些?如何設置WWDG窗口看門狗的超時時間
    發表于 09-24 07:33

    空閑中斷IDLE的超時時間如何設置

    空閑中斷IDLE的超時時間如何設置
    發表于 12-10 06:23

    如何設置獨立看門狗的超時時間?有哪些注意事項?

    如何設置獨立看門狗的超時時間?有哪些注意事項?
    發表于 01-18 06:25

    請問一下TCP建立連接超時時間怎么修改

    請問一下TCP建立連接超時時間怎么修改
    發表于 08-25 14:44

    有什么辦法解決WWDG最大超時時間太短的問題

    我想在 STM32F407 上使用其中一個看門狗,但令我驚訝的是 WWDG 的最大超時時間如此之短(大約 50 毫秒,具體取決于時鐘速度)。這是非常有限制的,例如扇區擦除花費的時間比這長得多(并且是
    發表于 12-23 06:19

    ESP32-S2如何設置socket recv的超時時間

    請教一下:如何設置socket recv的超時時間?參考的是TCP server例程,有其它的提供超時的例程嗎?謝謝!
    發表于 02-20 07:30

    有沒有辦法設置在STA模式下獲取DHCP地址的超時時間

    大家好。有沒有辦法設置在 STA 模式下獲取 DHCP 地址的超時時間?我想稍微增加它看起來 - 在慢速或低信號網絡環境中使用 4 秒。
    發表于 02-24 06:26

    怎么計算一個modbus的超時時間

    要怎么才能計算一個modbus的超時時間
    發表于 10-11 06:33

    時控開關怎么設置時時間

    藍牙時控開關:通過藍牙與手機連接,15米范圍內使用手機對開關進行無線控制。不用接觸開關,就可以控制手動開、關,也可以設置時時間自動開、關。
    的頭像 發表于 11-10 10:34 ?8501次閱讀

    socket連接超時如何處理

    實現以及網絡環境。 1. 理解Socket連接超時 在TCP/IP協議中,socket連接超時通常指的是在建立連接、發送數據或接收數據的過程中,由于沒有在預期時間內完成操作,系統自動終止連接。這個預期
    的頭像 發表于 11-01 16:48 ?402次閱讀

    socket 連接超時處理技巧

    在網絡編程中,Socket連接超時是一個常見的問題。處理超時的關鍵在于確保程序能夠優雅地處理這些情況,避免程序崩潰或者無響應。以下是一些處理Socket連接超時的技巧。 1. 設置合理
    的頭像 發表于 11-12 14:13 ?200次閱讀