声明式调用Feign《七》

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35781178/article/details/84196854

 feign 受retrofit ,jaxrs-2.0 和websocket 的影响,采用了声明式API接口的风格,将JAVA HTTP 客户端绑定到它的内部。feign 的首要目标是将Java http 客户端调用过程变得简单。feign 的源码:https://github.com/OpenFeign/feign

@FeignClient 注解声明一个Feign Client ,其中,value 未远程调用其他服务的服务名,FeignConfig.class 是Feign client 的配置类。

@Configuration注解表示该类是一个配置类,并注入一个BeanName为feignRetryer 的Retryer 的Bean。注入该Bean 之后,Feign 在远程调用失败后会进行重试。

FeignClient 注解被@Target({ElementType.TYPE}) 修饰,表示FeignClient注解的作用目标在接口上。@Retention(RetentionPolicy.RUNTIME) 注解表明该注解会在class字节码文件中存在。在运行时可以通过反射获取到。@Documented 表明该注解将被包含在javadoc 中。

@FeignClient 注解哟ing与创建声明式API接口,该接口是restful 风格的。Feign 被设计成插拔式的,可以注入其他组件和Feign 一起使用。ribbon 和feign 一起使用进行负载均衡。

value()和name() 一样,是被调用的服务的serviceId ,url()直接填写硬编码的rul地址。decode404()即404是被解码,还是抛异常。configuration()指明FeignClient的配置类,默认的配置类为FeignClientsConfiguration类,在缺省的情况下,这个类注入了默认的Decoder,Encoder和Contract等配置的Bean。fallback()为配置熔断器的处理类。

Feign 是一个伪java http 客户端,feign 不做任何的请求处理。feign 通过处理注解生成request 模板,从而简化了http api 的开发。开发人员可以使用注解的方式定制Request api 模板。在发送http request 请求之前,feign 通过处理注解的方式替换掉request 模板中的参数。生成真正的request ,并交给java http客户端去处理。

feign 通过包扫描注入FeignClient 的bean ,该源码在FeignClientRegistrar类中。首先程序启动时,会检查是否有@EnableFeignClients 注解,如果有该注解,则开启包扫描,扫描被@FeignClient注解的接口。

@Bean
@ConditionalOnMissingBean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {
    return new LoadBalancerFeignClient(new Default((SSLSocketFactory)null, (HostnameVerifier)null), cachingFactory, clientFactory);
}
@Configuration
@ConditionalOnClass({ApacheHttpClient.class})
@ConditionalOnProperty(
    value = {"feign.httpclient.enabled"},
    matchIfMissing = true
)
protected static class HttpClientFeignLoadBalancedConfiguration {
    @Autowired(
        required = false
    )
    private HttpClient httpClient;

    protected HttpClientFeignLoadBalancedConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean({Client.class})
    public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {
        ApacheHttpClient delegate;
        if (this.httpClient != null) {
            delegate = new ApacheHttpClient(this.httpClient);
        } else {
            delegate = new ApacheHttpClient();
        }

        return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
    }
}
由注解 @ConditionalOnClass({ApacheHttpClient.class}) 知,只需要在pom文件加上httpClient 的classpath 即可。另外需要在配置文件application.yml 中配置feign.httpclient.enabled=true  , @ConditionalOnProperty 显示,这个配置可以不写,因为默认为true。

在工程的pom 文件加上feign-client 的依赖,feign 就会采用httpClient 作为网络请求框架,而不是默认的HttpURLConnection。

<dependency>
   <groupId>com.netflix.feign</groupId>
   <artifactId>feign-httpclient</artifactId>
   <version>RELEASE</version>
</dependency>

如果想要feign 中使用okHttp 作为网络请求框架,只需要加上feign-okhttp 的依赖。

<dependency>
   <groupId>com.netflix.feign</groupId>
   <artifactId>feign-okhttp</artifactId>
   <version>RELEASE</version>
</dependency>

Feign 是如何实现负载均衡的:

FeignRibbonClientAutoConfiguration 类配置了client 的类型
扫描二维码关注公众号,回复: 4163863 查看本文章

(包括HttpURLConnection,OKHttp),最终向容器注入的是client的实现类LoadBalancerFeignClient,即负载均衡客户端。

盖棺定论:

feign 的源码实现过程如下:
1.首先通过@EnableFeignClients 注解开启FeignClient 的功能,只有这个注解存在,才会在程序启动时开启对@FeignClient 的报扫描。
2.根据Feign的规则实现接口,并在接口上面加上@FeignClient 注解。
3.程序启动后,会进行包扫码,扫描所有的@FeignClient注解的类,并将这些信息注入IOC容器中
4.当接口的方法被调用时,通过JDK的代理生成具体的requestTemplate 模板对象。
5.根据requestTemplate再生成http请求的request 对象。
6.request 对象交给client 去处理,其中client 的网络请求框架可以是HttpURLConnection,OKHttp,httpClient。
7.最后client 被封装到LoadBalanceClient 类,这个类结合类Ribbon 做到了负载均衡。

猜你喜欢

转载自blog.csdn.net/qq_35781178/article/details/84196854