Feign、httpclient、OkHttp3 結合使用

瘋狂創客圈 Java 高併發【 億級流量聊天室實戰】實戰系列 【博客園總入口html


瘋狂創客圈 正在進行分佈式和高併發基礎原理 的研習,好比下面的一些基礎性的內容:java

1、Netty Redis 億級流量 高併發 實戰git

2、高併發 springcloud + zookeeper 秒殺github

以及有關Springcloud 幾篇核心、重要的文章面試

1、Springcloud 配置, 史上最全 一文全懂算法

2、Feign Ribbon Hystrix 三者關係 , 史上最全 深度解析spring

3、SpringCloud gateway 詳解 , 史上最全apache

5、常識糾錯:Feign 默認不用 短鏈接服務器

6、Feign 核心原理,圖解併發

1 Feign 客戶端實現 類型

前面介紹到了經常使用的Feign客戶端實現類,大體以下:

(1) Client.Default類:默認的 feign.Client 客戶端實現類,內部使用HttpURLConnnection 完成HTTP URL請求處理;

(2) ApacheHttpClient 類:內部使用 Apache httpclient 開源組件完成HTTP URL請求處理的feign.Client 客戶端實現類;

(3) OkHttpClient類:內部使用 OkHttp3 開源組件完成HTTP URL請求處理的feign.Client 客戶端實現類。

(4) LoadBalancerFeignClient 類:這是一個特殊的 feign.Client 客戶端實現類。內部先使用 Ribbon 負載均衡算法計算server服務器,而後使用包裝的 delegate 客戶端實例,去完成 HTTP URL請求處理。

Feign 在啓動的時候,有兩個與feign.Client 客戶端實例相關的自動配置類,根據多種條件組合,去建立不一樣類型的 客戶端Spring IOC容器實例。

1.1.1 配置 LoadBalancerFeignClient 負載均衡容器實例

Feign有兩個與Client相關的自動配置類:

(1)org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration

(2)org.springframework.cloud.openfeign.FeignAutoConfiguration

第一個自動配置類,可以配置具備負載均衡能力的FeignClient容器實例;第二自動配置類,只能配置最原始的FeignClient容器實例。

具有負載均衡能力的 FeignClient 容器實例,所對應的類型爲 LoadBalancerFeignClient 類型。前面講到,在SpringCloud中,爲了達到高可用,一個微服務至少應該部署兩個以上節點,從這個角度來講,LoadBalancerFeignClient 容器實例,已經成爲事實上的標配。

事實上,第一個自動配置類 FeignRibbonClientAutoConfiguration,在容器的裝配次序上,是優先於第二個自動配置類 FeignAutoConfiguration 的。具體能夠參見其源碼,節選以下:

import com.netflix.loadbalancer.ILoadBalancer;
//….
@ConditionalOnClass({ILoadBalancer.class, Feign.class})
@Configuration
@AutoConfigureBefore({FeignAutoConfiguration.class})  // 本配置類具有優先權
@EnableConfigurationProperties({FeignHttpClientProperties.class})
@Import({
HttpClientFeignLoadBalancedConfiguration.class,  //配置:包裝ApacheHttpClient實例的負載均衡客戶端
OkHttpFeignLoadBalancedConfiguration.class, //配置:包裝OkHttpClient 實例的負載均衡客戶端
DefaultFeignLoadBalancedConfiguration.class  //配置:包裝Client.Default 實例的負載均衡客戶端
})
public class FeignRibbonClientAutoConfiguration {
    //空的構造器
    public FeignRibbonClientAutoConfiguration() {
    }
//….
}

從源碼中能夠看到,FeignRibbonClientAutoConfiguration 的自動配置有兩個前提條件:

(1)當前的類路徑中,存在 ILoadBalancer.class 接口

(2)當前的類路徑中,存在 Feign.class 接口

在這裏,重點說一下 ILoadBalancer.class 接口,該接口處於 ribbon 的jar包中。若是須要在類路徑中導入該jar包,則須要在Maven的pom.xml文件中,增長 ribbon 的相關依賴,具體以下:

<!-- ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

爲了加深你們對客戶端負載均衡的理解,這裏將 ILoadBalancer.class 接口的兩個重要的抽象方法列出來,具體以下:

package com.netflix.loadbalancer;
import java.util.List;
public interface ILoadBalancer {
    // 經過負載均衡算法計算server服務器
Server chooseServer(Object var1);
// 取得所有的服務器
List<Server> getAllServers();
//…
}

FeignRibbonClientAutoConfiguration 自動配置類,並無直接配置LoadBalancerFeignClient 容器實例,而是使用@Import註解,經過導入其餘配置類的方式,完成 LoadBalancerFeignClient 客戶端容器實例的配置。

分別導入瞭如下三個自動配置類

(1) HttpClientFeignLoadBalancedConfiguration.class

該配置類,負責配置一個包裝 ApacheHttpClient 實例的 LoadBalancerFeignClient負載均衡客戶端。

(2) OkHttpFeignLoadBalancedConfiguration.class

該配置類,負責配置一個包裝 OkHttpClient 實例的 LoadBalancerFeignClient負載均衡客戶端。

(3) DefaultFeignLoadBalancedConfiguration.class

該配置類,負責配置一個包裝 Client.Default 實例的 LoadBalancerFeignClient負載均衡客戶端。

1.1.2 包裝 ApacheHttpClient 實例的負載均衡容器實例

首先來看如何配置一個包裝 ApacheHttpClient 實例的負載均衡容器實例。這個IOC實例的配置,由 HttpClientFeignLoadBalancedConfiguration 自動配置類完成的,其源碼節選以下:

@Configuration
@ConditionalOnClass({ApacheHttpClient.class})
@ConditionalOnProperty(
    value = {"feign.httpclient.enabled"},
    matchIfMissing = true
)
class HttpClientFeignLoadBalancedConfiguration {
    //空的構造器
    HttpClientFeignLoadBalancedConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean({Client.class})
public Client feignClient(
CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory, HttpClient httpClient) 
{
        ApacheHttpClient delegate = new ApacheHttpClient(httpClient);
        return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory); // 進行包裝
    }
//…省略不相干的代碼
}

首先,來看源碼中的 feignClient(…)方法,分爲兩步:

(1)建立一個 ApacheHttpClient 類型的 feign.Client客戶端實例,該實例的內部使用 Apache httpclient 開源組件完成HTTP URL請求處理;

(2)建立一個 LoadBalancerFeignClient 負載均衡客戶端實例,將 ApacheHttpClient 實例包裝起來,而後返回LoadBalancerFeignClient 客戶端實例,做爲 feign.Client 類型的Spring IOC 容器實例。

而後,再看類 HttpClientFeignLoadBalancedConfiguration 上的兩個重要的註解:

(1)@ConditionalOnClass(ApacheHttpClient.class)

(2)@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)

這兩個條件的含義爲

(1)必須知足 ApacheHttpClient.class 在當前類路徑中存在;

(2)必須知足工程配置文件中 feign.httpclient.enabled 配置項的值爲 true ;

若是以上兩個條件同時知足,則 HttpClientFeignLoadBalancedConfiguration 自動配置工做就會啓動。

如何驗證呢?
首先在工程配置文件中,將配置項 feign.httpclient.enabled 的值,設置爲 false 。而後,在 HttpClientFeignLoadBalancedConfiguration 的 feignClient(…)方法內的某行打上斷點,從新啓動項目,注意觀察會發現,整個啓動過程當中,斷點沒有被命中。接下來,將配置項 feign.httpclient.enabled 的值設置爲 true,再一次啓動項目,斷點被命中。由此,能夠驗證 HttpClientFeignLoadBalancedConfiguration 自動配置類被啓動。

爲了知足 @ConditionalOnClass(ApacheHttpClient.class) 的條件要求,因爲ApacheHttpClient類的位置處於feign-httpclient相關的jar包中,因此,須要在pom文件加上 feign-httpclient 以及httpclient 組件相關的 Maven 依賴,具體以下:

<dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
            <version>9.5.1</version>
            <!--<version>${feign-httpclient.version}</version>-->
     </dependency>
<dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>${httpclient.version}</version>
    </dependency>

對於 feign.httpclient.enabled 配置項設置,根據 @ConditionalOnProperty 註解的屬性matchIfMissing=true 可知,這個能夠不用配置,在默認的狀況下就爲 true。換句話說,若是不作特別的配置,feign.httpclient.enabled 配置項的值,默認爲 true。

1.1.3 包裝 OkHttpClient 實例的負載均衡容器實例

接下來,來看如何配置一個包裝 OkHttpClient 實例的負載均衡容器實例。這個IOC實例的配置,由 OkHttpFeignLoadBalancedConfiguration 自動配置類完成的,其源碼節選以下:

@Configuration
@ConditionalOnClass({OkHttpClient.class})
@ConditionalOnProperty("feign.okhttp.enabled")
class OkHttpFeignLoadBalancedConfiguration {
    //空的構造器
    OkHttpFeignLoadBalancedConfiguration () {
    }

    @Bean
    @ConditionalOnMissingBean({Client.class})
public Client feignClient(
CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory, HttpClient httpClient) 
{
        OkHttpClient delegate = new OkHttpClient (httpClient);
        return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory); // 進行包裝
    }
//…省略不相干的代碼
}

首先,來看源碼中的 feignClient(…)方法,分爲兩步:

(1)建立一個 OkHttpClient 類型的 feign.Client客戶端實例,該實例的內部使用 OkHttp3 開源組件完成HTTP URL請求處理;

(2)建立一個 LoadBalancerFeignClient 負載均衡客戶端實例,將 OkHttpClient實例包裝起來,而後返回LoadBalancerFeignClient 客戶端實例,做爲 feign.Client 類型的Spring IOC 容器實例。

而後,再看類 OkHttpFeignLoadBalancedConfiguration 上的兩個重要的註解:

(1)@ConditionalOnClass(OkHttpClient.class)

(2)@ConditionalOnProperty("feign.okhttp.enabled")

這兩個條件的含義爲:

(1)必須知足 OkHttpClient.class 在當前類路徑中存在;

(2)必須知足工程配置文件中 feign.okhttp.enabled 配置項的值爲 true 。

若是以上兩個條件同時知足,則 OkHttpFeignLoadBalancedConfiguration 自動配置工做就會啓動。

爲了知足 @ConditionalOnClass(OkHttpClient.class) 的條件要求,因爲OkHttpClient.class 類的位置處於 feign-okhttp 相關的jar包中,因此,須要在pom文件加上 feign-okhttp 以及 okhttp3 相關的 Maven 依賴。具體以下:

<!-- OkHttp -->
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
</dependency>

<!-- feign-okhttp -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
</dependency>

對於 feign.okhttp.enabled 配置項設置,在默認的狀況下就爲 false。也就是說,若是須要使用feign-okhttp,則必定須要作特別的配置,在工程配置文件中,加上 feign.okhttp.enabled 配置項的值,而且值必須爲 true。若是須要使用 feign-okhttp,工程配置文件的配置項大體以下:

feign.httpclient.enabled=false
feign.okhttp.enabled=true

1.1.4 包裝 Client.Default 客戶端實例的負載均衡容器實例

最後,來看如何配置一個包裝默認Client.Default 客戶端實例的負載均衡容器實例。這個IOC實例的配置,由 DefaultFeignLoadBalancedConfiguration 自動配置類所完成的。該配置類,也就是 FeignRibbonClientAutoConfiguration 配置類經過 @import 註解所導入的第3個配置類。

DefaultFeignLoadBalancedConfiguration 的源碼節選以下:

package org.springframework.cloud.openfeign.ribbon;
//…省略import

@Configuration
class DefaultFeignLoadBalancedConfiguration {
    DefaultFeignLoadBalancedConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
 SpringClientFactory clientFactory)
  {
        return new LoadBalancerFeignClient(
new Default((SSLSocketFactory)null,
 (HostnameVerifier)null), cachingFactory, clientFactory);
    }
}

經過源碼能夠看出,若是前面的兩個配置類的條件沒有知足,feign.Client 的 IOC 容器實例沒有裝配,則:

(1) 建立一個 Client.Default 默認客戶端實例,該實例的內部,使用HttpURLConnnection 完成URL請求處理;

(2) 建立一個 LoadBalancerFeignClient 負載均衡客戶端實例,將 Client.Default 實例包裝起來,而後返回LoadBalancerFeignClient 客戶端實例,做爲 feign.Client 類型的Spring IOC 容器實例。

具體,請關注 Java 高併發研習社羣博客園 總入口


最後,介紹一下瘋狂創客圈:瘋狂創客圈,一個Java 高併發研習社羣博客園 總入口

瘋狂創客圈,傾力推出:面試必備 + 面試必備 + 面試必備 的基礎原理+實戰 書籍 《Netty Zookeeper Redis 高併發實戰

img


瘋狂創客圈 Java 死磕系列

  • Java (Netty) 聊天程序【 億級流量】實戰 開源項目實戰

  • Netty 源碼、原理、JAVA NIO 原理
  • Java 面試題 一網打盡
  • 瘋狂創客圈 【 博客園 總入口 】


y Zookeeper Redis 高併發實戰](https://www.cnblogs.com/crazymakercircle/p/11397271.html)》

[外鏈圖片轉存中...(img-Xmc93wKV-1575216360903)]


瘋狂創客圈 Java 死磕系列

  • Java (Netty) 聊天程序【 億級流量】實戰 開源項目實戰

  • Netty 源碼、原理、JAVA NIO 原理
  • Java 面試題 一網打盡
  • 瘋狂創客圈 【 博客園 總入口 】

相關文章
相關標籤/搜索