Zuul進階篇-okhttp替換httpclient

前言
在當下微服務的場景下,HTTP請求方式成爲了集成各服務的最佳方式。在 Java 平臺上,Java 標準庫提供了 HttpURLConnection 類來支持 HTTP 通訊。不過 HttpURLConnection 本身的 API 不夠友好,所提供的功能也有限。大部分 Java 程序都選擇使用 Apache 的開源項目 HttpClient 作爲 HTTP 客戶端。Apache HttpClient 庫的功能強大,使用率也很高,基本上是 Java 平臺中事實上的標準 HTTP 客戶端。本章介紹的是由 Square 公司開發的 OkHttp,是一個專注於性能和易用性的 HTTP 客戶端。
OkHttp 庫的設計和實現的首要目標是高效。這也是選擇 OkHttp 的重要理由之一。OkHttp 提供了對最新的 HTTP 協議版本 HTTP/2 和 SPDY 的支持,這使得對同一個主機發出的所有請求都可以共享相同的套接字連接。如果 HTTP/2 和 SPDY 不可用,OkHttp 會使用連接池來複用連接以提高效率。OkHttp 提供了對 GZIP 的默認支持來降低傳輸內容的大小。OkHttp 也提供了對 HTTP 響應的緩存機制,可以避免不必要的網絡請求。當網絡出現問題時,OkHttp 會自動重試一個主機的多個 IP 地址。
下面將基於springcloud採用Okhttp替換默認的HttpClient 。

本章概要
1、Zuul中Okhttp應用;
2、Feign中Okhttp應用;

Zuul中Okhttp應用
本小節將介紹基於springcloud-gateway-zuul工程的實現。

1、通過官方可以看到如下說明:


2、參照上述官方說明,首先在POM中添加如下依賴:
<!-- okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>

3、在application.properties中添加配置:
#ribbon use okhttp
ribbon.httpclient.enabled=false
ribbon.okhttp.enabled=true

4、依次啓動Eureka Server、Config Server、service1、Consumer1(3331)、api-gateway(5001)五個相關服務,並設定api-gateway服務的log級別爲debug,此時訪問http://127.0.0.1:5001/api-consumer01-url/hystrix/feign/getServerInfo/service1,postman獲取響應如下圖:


5、我們來具體看下日誌內容:
RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration matched:
- AnyNestedCondition 1 matched 1 did not; NestedCondition on RibbonCommandFactoryConfiguration.OnRibbonHttpClientCondition.RibbonProperty@ConditionalOnProperty (ribbon.httpclient.enabled) found different value in property 'ribbon.httpclient.enabled'; NestedCondition on RibbonCommandFactoryConfiguration.OnRibbonHttpClientCondition.ZuulProperty @ConditionalOnProperty (zuul.ribbon.httpclient.enabled) matched (RibbonCommandFactoryConfiguration.OnRibbonHttpClientCondition)

RibbonCommandFactoryConfiguration.OkHttpRibbonConfigurationmatched:
-@ConditionalOnClass found required class 'okhttp3.OkHttpClient'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- AnyNestedCondition 1 matched 1 did not; NestedCondition on RibbonCommandFactoryConfiguration.OnRibbonOkHttpClientCondition.RibbonProperty@ConditionalOnProperty (ribbon.okhttp.enabled) matched; NestedCondition on RibbonCommandFactoryConfiguration.OnRibbonOkHttpClientCondition.ZuulProperty @ConditionalOnProperty (zuul.ribbon.okhttp.enabled) did not find property 'zuul.ribbon.okhttp.enabled' (RibbonCommandFactoryConfiguration.OnRibbonOkHttpClientCondition)

紅色標識部分即爲我們在2、3步驟中的配置生效反饋,此時可能我們還會看到類似(zuul.ribbon.httpclient.enabled)配置說明,通過6中的源碼即可瞭解其已經被廢棄,並在下一個版本中將被移除。

6、其主要涉及源碼爲RibbonCommandFactoryConfiguration,通過前幾章我們已經很清楚Zuul的負載均衡實現就是通過Ribbon實現的,故Http客戶端的配置自然也是對Ribbon組件的配置,對應日誌中核心源代碼:
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnRibbonHttpClientCondition.class)
@interface ConditionalOnRibbonHttpClient { }

private static class OnRibbonHttpClientCondition extends AnyNestedCondition {
   public OnRibbonHttpClientCondition() {
      super(ConfigurationPhase.PARSE_CONFIGURATION);
   }

   @Deprecated //remove in Edgware"
   @ConditionalOnProperty(name = "zuul.ribbon.httpclient.enabled", matchIfMissing = true)
   static class ZuulProperty {}

   @ConditionalOnProperty(name = "ribbon.httpclient.enabled", matchIfMissing = true)
   static class RibbonProperty {}
}

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnRibbonOkHttpClientCondition.class)
@interface ConditionalOnRibbonOkHttpClient { }

private static class OnRibbonOkHttpClientCondition extends AnyNestedCondition {
   public OnRibbonOkHttpClientCondition() {
      super(ConfigurationPhase.PARSE_CONFIGURATION);
   }

   @Deprecated //remove in Edgware"
   @ConditionalOnProperty("zuul.ribbon.okhttp.enabled")
   static class ZuulProperty {}

   @ConditionalOnProperty("ribbon.okhttp.enabled")
   static class RibbonProperty {}
}
小節:源代碼中通過@Conditional實現了條件加載,是上述幾個步驟的配置與分析結果的基礎。其實Cloud還提供了RestClientHttp客戶端實現,相對以上兩種方式,屬於第三選擇,故不做分析。

Feign中Okhttp應用
本小節將介紹基於springcloud-eureka-consumer工程的實現,其實現過程與Zuul中應用非常類似,本小節不過過多的分析,把實踐過程簡要記錄。

1、首先在POM中添加如下依賴:
<!-- okhttp -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>

通過依賴樹可以看到在feign-okhttp中已經存在上述的okhttp依賴


2、在application.properties中添加配置:
#feign use okhttp
feign.httpclient.enabled=false
feign.okhttp.enabled=true

3、如下爲啓動服務請求後的日誌記錄,紅色部分爲關注重點:
[2017-06-27 16:44:35.728] [DEBUG] [restartedMain] o.s.c.e.PropertySourcesPropertyResolver -Found key 'feign.okhttp.enabled' in [applicationConfigurationProperties] with type [String]
[2017-06-27 16:44:35.728] [DEBUG] [restartedMain] o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'autoConfigurationReport'
[2017-06-27 16:44:35.729] [DEBUG] [restartedMain] o.s.c.a.ConfigurationClassBeanDefinitionReader - Registered bean definition for imported class 'org.springframework.cloud.netflix.feign.ribbon.FeignRibbonClientAutoConfiguration$OkHttpFeignLoadBalancedConfiguration'
[2017-06-27 16:44:35.729] [DEBUG] [restartedMain] o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.boot.autoconfigure.condition.BeanTypeRegistry'
[2017-06-27 16:44:35.735] [DEBUG] [restartedMain] o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.boot.autoconfigure.condition.BeanTypeRegistry'
[2017-06-27 16:44:35.736] [DEBUG] [restartedMain] o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'autoConfigurationReport'
[2017-06-27 16:44:35.736] [DEBUG] [restartedMain] o.s.c.a.ConfigurationClassBeanDefinitionReader -Registering bean definition for @Bean method org.springframework.cloud.netflix.feign.ribbon.FeignRibbonClientAutoConfiguration$OkHttpFeignLoadBalancedConfiguration.feignClient()

小節:以上即爲在Feign中如何使用Okhttp,非常簡單易用,其自動裝配源碼在FeignRibbonClientAutoConfiguration中閱讀即可。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章