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中阅读即可。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章