feign直接走熔断_Java后端精选技术:深入理解Feign

什么是Feign

Feign是由Retrofit,JAXRS-2.0和WebSocket启发的一个java到http客户端绑定。 Feign的主要目标是将Java Http Clients变得简单。Feign的源码地址:https://github.com/OpenFeign/feign

写一个Feign

在我之前的博文有写到如何用Feign去消费服务,简单的实现一个Feign客户端,首先通过@FeignClient,客户端,其中value为调用其他服务的名称,FeignConfig.class为FeignClient的配置文件,代码如下:

04dfcd98d5f671f33acb0f4f5379b8cc.png

其配置文件如下:

b26bc0031b45155a0afa70957e74bde1.png

查看FeignClient的源码,其代码如下:

c70a42c6fcccec76e71dc053d712912a.png

feign 用于声明具有该接口的REST客户端的接口的注释应该是创建(例如用于自动连接到另一个组件。 如果功能区可用,那将是 用于负载平衡后端请求,并且可以配置负载平衡器 使用与伪装客户端相同名称(即值)@RibbonClient 。

其中value()和name()一样,是被调用的 service的名称。 url(),直接填写硬编码的url,decode404()即404是否被解码,还是抛异常;configuration(),标明FeignClient的配置类,默认的配置类为FeignClientsConfiguration类,可以覆盖Decoder、Encoder和Contract等信息,进行自定义配置。fallback(),填写熔断器的信息类。

FeignClient的配置

默认的配置类为FeignClientsConfiguration,这个类在spring-cloud-netflix-core的jar包下,打开这个类,可以发现它是一个配置类,注入了很多的相关配置的bean,包括feignRetryer、FeignLoggerFactory、FormattingConversionService等,其中还包括了Decoder、Encoder、Contract,如果这三个bean在没有注入的情况下,会自动注入默认的配置。

  • Decoder feignDecoder: ResponseEntityDecoder(这是对SpringDecoder的封装)
  • Encoder feignEncoder: SpringEncoder
  • Logger feignLogger: Slf4jLogger
  • Contract feignContract: SpringMvcContract
  • Feign.Builder feignBuilder: HystrixFeign.Builder

代码如下:

7d4c5fec46e39379a10a9817ae7719d3.png

重写配置:

你可以重写FeignClientsConfiguration中的bean,从而达到自定义配置的目的,比如FeignClientsConfiguration的默认重试次数为Retryer.NEVER_RETRY,即不重试,那么希望做到重写,代码如下:

ded0bcc8513c3f6b8c30114e25a75b74.png

在上述代码更改了该FeignClient的重试次数,重试间隔为100ms,最大重试时间为1s,重试次数为5次。

Feign的工作原理

feign是一个伪客户端,即它不做任何的请求处理。Feign通过处理注解生成request,从而实现简化HTTP API开发的目的,即开发人员可以使用注解的方式定制request api模板,在发送http request请求之前,feign通过处理注解的方式替换掉request模板中的参数,这种实现方式显得更为直接、可理解。

通过包扫描注入FeignClient的bean,该源码在FeignClientsRegistrar类: 首先在启动配置上检查是否有@EnableFeignClients注解,如果有该注解,则开启包扫描,扫描被@FeignClient注解接口。代码如下:

3a7bf9f1fe6e38cfcf5988640f0fdb2c.png

扫描到FeignClient后,将信息取出,以bean的形式注入到ioc容器中,源码如下:

e8a556f0781d726122b499f8cb61d242.png
29c7250a31138285b3c9de5251b918de.png

注入bean之后,通过jdk的代理,当请求Feign Client的方法时会被拦截,代码在ReflectiveFeign类,代码如下:

a85f8b6bc4a1d42ab713770d8f1f4a80.png

在SynchronousMethodHandler类进行拦截处理,当被拦截会根据参数生成RequestTemplate对象,该对象就是http请求的模板,代码如下:

ce01d26b8cb66d282002e8276ac4f833.png

其中有个executeAndDecode()方法,该方法是通RequestTemplate生成Request请求对象,然后根据用client获取response。

7000a1a580739e5c0a00774379f0b693.png

Client组件

其中Client组件是一个非常重要的组件,Feign最终发送request请求以及接收response响应,都是由Client组件完成的,其中Client的实现类,只要有Client.Default,该类由HttpURLConnnection实现网络请求,另外还支持HttpClient、Okhttp.

首先来看以下在FeignRibbonClient的自动配置类,FeignRibbonClientAutoConfiguration ,主要在工程启动的时候注入一些bean,其代码如下:

381c1623f9e96481283adaf162a4f75a.png

在缺失配置feignClient的情况下,会自动注入new Client.Default(),跟踪Client.Default()源码,它使用的网络请求框架为HttpURLConnection,代码如下:

3f8a140128b0ea15940b33e204a86189.png

怎么在feign中使用HttpClient,查看FeignRibbonClientAutoConfiguration的源码

fdc738517dcef923998c445d5c39e777.png

从代码@ConditionalOnClass(ApacheHttpClient.class)注解可知道,只需要在pom文件加上HttpClient的classpath就行了,另外需要在配置文件上加上feign.httpclient.enabled为true,从 @ConditionalOnProperty注解可知,这个可以不写,在默认的情况下就为true.

在pom文件加上:

93f80018a458e14c6fc851480a6ab849.png

同理,如果想要feign使用Okhttp,则只需要在pom文件上加上feign-okhttp的依赖:

bc3a00654ad46694d6f60b7e7ee88e2c.png

feign的负载均衡是怎么样实现的呢?

通过上述的FeignRibbonClientAutoConfiguration类配置Client的类型(httpurlconnection,okhttp和httpclient)时候,可知最终向容器注入的是LoadBalancerFeignClient,即负载均衡客户端。现在来看下LoadBalancerFeignClient的代码:

f309bd8801e1898ed4db97097440272d.png

其中有个executeWithLoadBalancer()方法,即通过负载均衡的方式请求。

9fe5268c8ed9125590bd9fe4770a46f7.png

其中服务在submit()方法上,点击submit进入具体的方法,这个方法是LoadBalancerCommand的方法:

d6437581af49a7a75d91dd48f9293edd.png

上述代码中有个selectServe(),该方法是选择服务的进行负载均衡的方法,代码如下:

326887ab9b6f33a5a319576fbeee1368.png

最终负载均衡交给loadBalancerContext来处理,即之前讲述的Ribbon,在这里不再重复。

总结

总到来说,Feign的源码实现的过程如下:

  • 首先通过@EnableFeignCleints注解开启FeignCleint
  • 根据Feign的规则实现接口,并加@FeignCleint注解
  • 程序启动后,会进行包扫描,扫描所有的@ FeignCleint的注解的类,并将这些信息注入到ioc容器中。
  • 当接口的方法被调用,通过jdk的代理,来生成具体的RequesTemplate
  • RequesTemplate在生成Request
  • Request交给Client去处理,其中Client可以是HttpUrlConnection、HttpClient也可以是Okhttp
  • 最后Client被封装到LoadBalanceClient类,这个类结合类Ribbon做到了负载均衡。
原文地址:https://dwz.cn/iXjQZJdr
作者:方志朋
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值