SpringCloud FeignClient的坑(httpClient連線池的使用)

SpringCloud FeignClient的坑(httpClient連線池的使用)

前言

在頭條上已經發布過不少的文章了,根據文章的瀏覽量來看,go語言的市場需求明顯是小於java的需求量的,最近也開始釋出一下以前使用java和springcloud,springboot裡遇到的一些避坑文章; 個人感覺go在雲原生這個場景裡將會不斷地被髮展,在雲原生環境下,沒有任何一個語言可能和其匹敵,RUST也許會有一定的競爭壓力。 作為service mesh未來的雲環境架構, springcloud的原有專案會慢慢地轉換; 先說了些感悟, 今天要分享的是OpenFeign裡的一個小坑。 OpenFeign是springcloud裡用的比較多的http RPC的一個架構, FeignClient是這個架構中的一個Client的入口點。

SpringCloud FeignClient的坑(httpClient連線池的使用)

在壓力測試的過程中發現的問題;併發執行緒數較多時,持續一段時間後,開始出現請求失敗。日誌發現的錯誤有兩種:

一種是ribbon報找不到目標服務,錯誤資訊如下:

Caused by: com。netflix。client。ClientException: Load balancer does not have available server for client: halo-framework-example-server

at com。netflix。loadbalancer。LoadBalancerContext。getServerFromLoadBalancer(LoadBalancerContext。java:483)

at com。netflix。loadbalancer。reactive。LoadBalancerCommand$1。call(LoadBalancerCommand。java:184)

at com。netflix。loadbalancer。reactive。LoadBalancerCommand$1。call(LoadBalancerCommand。java:180)

at rx。Observable。unsafeSubscribe(Observable。java:10327)

at rx。internal。operators。OnSubscribeConcatMap。call(OnSubscribeConcatMap。java:94)

at rx。internal。operators。OnSubscribeConcatMap。call(OnSubscribeConcatMap。java:42)

一種是socket底層報出的Unkonw Host的錯誤

at java。net。PlainSocketImpl。socketConnect(Native Method) ~[na:1。8。0_152]

at java。net。AbstractPlainSocketImpl。doConnect(AbstractPlainSocketImpl。java:350) ~[na:1。8。0_152]

at java。net。AbstractPlainSocketImpl。connectToAddress(AbstractPlainSocketImpl。java:206) ~[na:1。8。0_152]

at java。net。AbstractPlainSocketImpl。connect(AbstractPlainSocketImpl。java:188) ~[na:1。8。0_152]

at java。net。SocksSocketImpl。connect(SocksSocketImpl。java:392) ~[na:1。8。0_152]

at java。net。Socket。connect(Socket。java:589) ~[na:1。8。0_152]

at sun。net。NetworkClient。doConnect(NetworkClient。java:175) ~[na:1。8。0_152]

at sun。net。www。http。HttpClient。openServer(HttpClient。java:463) ~[na:1。8。0_152]

at sun。net。www。http。HttpClient。openServer(HttpClient。java:558) ~[na:1。8。0_152]

at sun。net。www。http。HttpClient。(HttpClient。java:242) ~[na:1。8。0_152]

at sun。net。www。http。HttpClient。New(HttpClient。java:339) ~[na:1。8。0_152]

at sun。net。www。http。HttpClient。New(HttpClient。java:357) ~[na:1。8。0_152]

檢視feignclient的原始碼

@Import({ HttpClientFeignLoadBalancedConfiguration。class, OkHttpFeignLoadBalancedConfiguration。class, DefaultFeignLoadBalancedConfiguration。class })public class FeignRibbonClientAutoConfiguration {

@Configuration@ConditionalOnClass(ApacheHttpClient。class)@ConditionalOnProperty(value = “feign。httpclient。enabled”, matchIfMissing = true)class HttpClientFeignLoadBalancedConfiguration {

上面是autoconfiguration的方式對feignClient進行配置。 可以看到有三種方式, 分別是HttpClientFeignLoadBalancedConfiguration。class, OkHttpFeignLoadBalancedConfiguration。class,

DefaultFeignLoadBalancedConfiguration。class

這三種方式, 其中最後一種方式DefaultFeignLoadBalancedConfiguration是預設方式,也就是直接透過Httpclient進行http的呼叫,不使用連線池的方式,只有上面兩種方式是支援連線池的方式, Openfeign元件透過型別ConditionONClass的方式,進行條件配置,如果引入了OKHttpClient或者Apache HttpClient的包才會使用到http的連線池, 由於預設是沒有import這裡的兩個包,所以預設以不帶連線池的實現方式來實現httpclient,也就出現上面的問題。

知道了問題所在,解決的方法,就是引入相應的寶貝即可。

SpringCloud FeignClient的坑(httpClient連線池的使用)

結束語

SpringCloud在最新的版本里已經對robbin進行了捨棄,這個robbin裡有不少的問題,記得當時都是做了一些自己的封裝。 以後可以分享一下這塊的體驗和思路。

SpringCloud FeignClient的坑(httpClient連線池的使用)

頂部