• Feign、httpclient、OkHttp3 结合使用


    疯狂创客圈 Java 高并发【 亿级流量聊天室实战】实战系列 【博客园总入口


    疯狂创客圈 正在进行分布式和高并发基础原理 的研习,比如下面的一些基础性的内容:

    一、Netty Redis 亿级流量 高并发 实战

    二、高并发 springcloud + zookeeper 秒杀

    以及有关Springcloud 几篇核心、重要的文章

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

    二、Feign Ribbon Hystrix 三者关系 , 史上最全 深度解析

    三、SpringCloud gateway 详解 , 史上最全

    五、常识纠错:Feign 默认不用 短连接

    六、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) 聊天程序【 亿级流量】实战 开源项目实战

    y Zookeeper Redis 高并发实战](https://www.cnblogs.com/crazymakercircle/p/11397271.html)》

    [外链图片转存中...(img-Xmc93wKV-1575216360903)]


    疯狂创客圈 Java 死磕系列

    • Java (Netty) 聊天程序【 亿级流量】实战 开源项目实战

  • 相关阅读:
    struts1:(Struts)ActionForm类及表单数据验证
    前端基础
    JavaScript 开发进阶:理解 JavaScript 作用域和作用域链
    vue+webpack一些知识
    gulp简单使用小记
    如何在Github Pages搭建自己写的页面?
    十大名茶
    中国六大茶类
    从零开始用gulp
    15 个有趣的 JavaScript 与 CSS 库
  • 原文地址:https://www.cnblogs.com/crazymakercircle/p/11968479.html
Copyright © 2020-2023  润新知