这是我参与更文挑战的第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:
拦截请求,并对请求做一些自定义处理。