计算机系统应用教程网站

网站首页 > 技术文章 正文

Feign的七大核心组件介绍

btikc 2024-09-10 12:02:44 技术文章 12 ℃ 0 评论

上篇文章介绍了Feign的介绍和入门,这次我们介绍下Feign的七大核心组件。

相信稍微了解Feign的小伙伴都知道,Feign底层其实是基于JDK动态代理实现的,所以Feign.builder()最终构造的是一个代理对象,Feign在构建动态代理的时候,会去解析方法上的注解和参数,获取Http请求需要用到基本参数以及和这些参数和方法参数的对应关系。比如Http请求的url、请求体是方法中的第几个参数、请求头是方法中的第几个参数等……之后在构建Http请求时,就知道请求路径以及方法的第几个参数对应是Http请求的哪部分数据,当调用动态代理方法的时候,Feign就会将上述解析出来的Http请求基本参数和方法入参组装成一个Http请求,然后发送Http请求,获取响应,再根据响应的内容的类型将响应体的内容转换成对应的类型,这就是Feign的大致原理。为更好的说明,从网上找到下图

在整个Feign动态代理生成和调用过程中,需要依靠Feign的一些核心组件来协调完成,如下图源码所示是Feign的一些核心组件。

这些核心组件可以根据项目实际需要通过Feign.builder()进行替换。由于组件比较很多,这里仅挑几个重要的进行说明。

1、Contract

Feign在构建动态代理的时候,会去解析方法上的注解和参数,获取Http请求需要用到基本参数,而这个Contract接口的作用就是用来解析Feign原生注解的。


解析时,会为每个方法生成一个MethodMetadata对象

MethodMetadata就封装了Http请求需要用到基本参数以及这些参数和方法参数的对应关系。

2、Encoder

通过名字可以看出来,这个其实用来编码的。具体的作用就是将请求体对应的方法参数序列化成字节数组,如下图所示

Feign默认的Encoder实现只支持请求体对应的方法参数类型为String和字节数组。


如果是其它类型,比如说请求体对应的方法参数类型为User.class类型,此时就无法对User对象进行序列化,这就导致默认情况下,这个Encoder的实现很难用,于是Spring就实现了自己的Encoder接口。它可以将任意请求体对应的方法参数类型对象序列化成字节数组,源码如下图。


3、Decoder

Decoder的作用恰恰是跟Encoder相反,Encoder是将请求体对应的方法参数序列化成字节数组,而Decoder其实就是将响应体由字节流反序列化成方法返回值类型的对象。Decoder默认情况下跟Encoder的默认情况是一样的,只支持反序列化成字节数组或者是String。

Spring也同样实现了Decoder,扩展它的功能,可以将响应体对应的字节流反序列化成任意返回值类型对象。


4、Client

从接口方法的参数和返回值可以看出,这其实就是动态代理对象最终用来执行Http请求的组件,默认实现就是通过JDK提供的HttpURLConnection来的。

除了这个默认的,Feign还提供了基于HttpClient和OkHttp实现。在项目中,要想替换默认的实现,只需要引入相应的依赖,在构建Feign.builder()时设置一下就可以了,非常灵活。

除了上述的三个实现外,最重要的当然是属于它基于负载均衡的实现,如下是OpenFeign用来整合Ribbon的核心实现。

在调用服务时Client会根据服务名,从Ribbon中获取一个服务实例的信息,也就是ip和端口,然后通过ip和端口向服务实例发送Http请求。

5、InvocationHandlerFactory

InvocationHandler我相信大家应该都不陌生,对于JDK动态代理来说,必须得实现InvocationHandler才能创建动态代理,InvocationHandler的invoke方法实现就是动态代理走的核心逻辑,而InvocationHandlerFactory其实就是创建InvocationHandler的工厂。从这里就可以猜到,通过InvocationHandlerFactory创建的InvocationHandler应该就是Feign动态代理执行的核心逻辑,InvocationHandlerFactory默认实现是下面这个。

SpringCloud环境下默认也是使用它的这个默认实现,直接去看看InvocationHandler的实现类FeignInvocationHandler。


从实现可以看出,除了Object类的一些方法,最终会调用方法对应的MethodHandler的invoke方法。所以注意,这个MethodHandler就封装了Feign执行Http调用的核心逻辑。

虽然说默认情况下SpringCloud使用是默认实现,最终使用FeignInvocationHandler,但是当其它框架整合SpringCloud生态的时候,为了适配OpenFeign,有时会自己实现InvocationHandler,比如常见的限流熔断框架Hystrix和Sentinel都实现了自己的InvocationHandler。这样就可以对MethodHandler执行前后,也就是Http接口调用前后进行限流降级等操作。

6、RequestInterceptor

RequestInterceptor它其实是一个在发送请求前的一个拦截接口,通过这个接口,在发送Http请求之前再对Http请求的内容进行修改,比如我们可以设置一些接口需要的公共参数,如鉴权token之类的。


7、Retryer

这是一个重试的组件,默认实现如下。默认情况下,最大重试5次。

在SpringCloud下,并没有使用上面那个实现,而使用的是下面这个实现。


总结

这一节主要是介绍了7个Feign的核心组件以及Spring对应的扩展实现,为了方便查看,整理了如下表格:

接口

作用

Feign默认实现

Spring实现

Contract

解析方法注解和参数,将Http请求参数和方法参数对应

Contract.Default

SpringMvcContract

Encoder

将请求体对应的方法参数序列化成字节数组

Encoder.Default

SpringEncoder

Decoder

将响应体的字节流反序列化成方法返回值类型对象

Decoder.Default

SpringDecoder

Client

发送Http请求

Client.Default

LoadBalancerFeignClient

InvocationHandlerFactory

InvocationHandler工厂,动态代理核心逻辑

InvocationHandlerFactory.Default

RequestInterceptor

在发送Http请求之前,再对Http请求的内容进行拦截修改

Retryer

重试组件

Retryer.Default

除了这些之外,其它组件这里就没有列出,有兴趣的可以自己查看!下次将进行Feign核心原理分析

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表