这是我参与更文挑战的第18天,活动详情查看:更文挑战
一、前言
Feign
是一个声明式的REST
客户端,它的目的就是让REST
调用更加简单。
Feign
提供了HTTP
请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP
请求的参数、格式、地址等信息。
- 而且
Feign
会完全代理HTTP
请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。 Spring Cloud
对Feign
进行了封装,使其支持SpringMVC
标准注解和HttpMessageConverters
。Feign
可以与Eureka
和Ribbon
组合使用以支持负载均衡,与Hystrix
组合使用,支持熔断回退。
Feign
和 Openfeign
的区别 :
Feign
最早是由 Netflix
公司进行维护的,后来 Netflix
不再对其进行维护,最终 Feign
由社区进行维护,更名为 Openfeign
。
二、Feign
重要组件
组件,如图:
Contract
契约组件
在
Feign
中可以通过定义API
接口的方式来调用远程的Http API
,在定义调用Client
的时候需要增加一些注解来描述这个调用API
的基本信息,比如请求类型是GET
还是POST
,请求的URI
是什么。Contract
允许用户自定义契约去解析注解信息,最典型的应用场景就是在Spring Cloud
中使用Feign
,可以使用Spring MVC
的注解来定义Feign
的客户端,这是因为Spring Cloud OpenFeign
中实现了自己的SpringMvcContract
。
Encoder
编码组件
通过该组件我们可以将请求信息采用指定的编码方式进行编码后传输。
例如:把一个对象转成
json
格式。
Decoder
解码组件
Decoder
将相应数据解码成对象。例如:将
json
转换成本地的一个Java
对象。
ErrorDecoder
异常解码器
当被调用方发生异常后,可以在
ErrorDecoder
中将响应的数据转换成具体的异常返回给调用方,适合内部服务之间调用,但不想通过指定的字段来判断是否成功的场景,直接用自定义异常代替。
Logger
日志记录
Logger
组件是负责Feign
中记录日志的,可以指定Logger
的级别以及自定义日志的输出。
Client
请求执行组件
Client
是负责HTTP
请求执行的组件,Feign
将请求信息封装好后会交由Client
来执行,Feign
中默认的Client
是通过JDK
的HttpURLConnection
来发起请求的,在每次发送请求的时候,都会创建新的HttpURLConnection
链接,使用默认的方式,Feign
的性能会很差,原因就是使用了HttpURLConnection
。你可以通过扩展该接口,使用Apache HttpClient
等基于连接池的高性能HTTP
客户端。
Retryer
重试组件
Retryer
是负责重试的组件,Feign
内置了重试器,当HTTP
请求出现IO
异常时,Feign
会限定一个最大重试次数来进行重试操作。
InvocationHandlerFactory
代理
InvocationHandlerFactory
采用JDK
的动态代理方式生成代理对象,定义的Feign Client
是接口,当调用这个接口中定义的方法时,实际上是要去调用远程的HTTP API
,这里用了动态代理方式,当调用某个方法时,会进入代理中真正的去调用远程HTTP API
。
RequestInterceptor
请求拦截器
可以为
Feign
添加多个拦截器,在请求执行前设置一些扩展的参数信息。
QueryMapEncoder
参数查询
QueryMapEncoder
是针对实体类参数查询的编码器,可以基于QueryMapEncoder
将实体类生成对应的查询参数。
其他重要组件:
Feign.Builder
:FeignClient
的一个实例构造器FeignClient
:feign
的核心入口,里面包含了一系列的组件:Encoder
、Decoder
、Logger
、Contract
等等
三、执行过程
单纯的 Feign
执行过程,如下:
- 动态代理 (
InvocationHandlerFactory
),生成对应的实体类:
在使用
feign
时,会定义对应的接口类,在接口类上使用Feign
自带的注解来标识HTTP
的请求参数信息,当调用接口对应的方法时,Feign
内部会基于面向接口的动态代理方式生成实现类,将请求调用委托到动态代理实现类,负责动态代理的组件是InvocationHandlerFactory
。
- 根据规则(
Contract
)解析注解:
根据
Contract
规则,解析接口类的注解信息,翻译成Feign
内部能识别的信息。
Feign
默认有一套自己的协议规范,也可以自定义其他的规范来进行扩展,在Spring Cloud OpenFeign
中就扩展了SpringMvcContract
,这样做的目的是为了降低学习和使用成本,客户端和服务端使用同一个接口定义,发布成SDK
给调用方使用。
- 生成对应请求对象(
MethodHandler
):
MethodHandler
在执行的时候会生成Request
对象,在构建Request
对象的时候会为其设置拦截器,交由Client
执行前记录一些日志,Client
执行完成后也记录一些日志,然后使Decoder
进行相应结果的解码操作,并返回结果。
- 请求拦截器
Interceptor
:
拦截请求,并对请求做一些自定义处理。