微服务面试准备——Feign

微服务面试准备——Feign_第1张图片

  • Contract 契约组件

在 Feign 中可以通过定义 API 接口的方式来调用远程的 Http API,在定义调用 Client 的时候需要增加一些注解来描述这个调用 API 的基本信息,比如请求类型是 GET 还是 POST,请求的 URI 是什么。Contract 允许用户自定义契约去解析注解信息,最典型的应用场景就是在 Spring Cloud 中使用 Feign,我们可以使用 Spring MVC 的注解来定义 Feign 的客户端,这是因为 Spring Cloud OpenFeign 中实现了自己的 SpringMvcContract。

  • Encoder 编码组件

通过该组件我们可以将请求信息采用指定的编码方式进行编码后传输。

  • Decoder 解码组件

Decoder 将相应数据解码成对象。

  • 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_第2张图片

在使用 feign 时,我们会定义对应的接口类,在接口类上使用 Feign 自带的注解来标识 HTTP 的请求参数信息,当调用接口对应的方法时,Feign 内部会基于面向接口的动态代理方式生成实现类,将请求调用委托到动态代理实现类,负责动态代理的组件是 InvocationHandlerFactory。

根据 Contract 规则,解析接口类的注解信息,翻译成 Feign 内部能识别的信息。Feign 默认有一套自己的协议规范,我们也可以自定义其他的规范来进行扩展,在 Spring Cloud OpenFeign中就扩展了 SpringMvcContract,这样做的目的是为了降低学习和使用成本,客户端和服务端使用同一个接口定义,发布成 SDK 给调用方使用。

MethodHandler 在执行的时候会生成 Request 对象,在构建 Request 对象的时候会为其设置拦截器,交由 Client 执行前记录一些日志,Client 执行完成后也记录一些日志,然后使 Decoder 进行相应结果的解码操作,并返回结果。

Feign-源码分析

首先来看下 Feign 执行请求的源码,从 Feign 这个类开始,通过 Feign 类提供的 Builder 模式,我们可以构建出一个 Feign Client,通过这个 Client 就可以调用远程的 API,看下 Builder 类中的参数信息,如 Logger、Client。接下来看下 target 方法,target 是最终生成代理类的方法,首先会进入 build 方法,在 build 中创建了 ReflectiveFeign 对象,最终调用的是 newInstance 方法,解析出 MethodHandler,然后创建 InvocationHandler 生成代理类,接着查看 SynchronousMethodHandler 类,在 invoke 方法中就是调用远程 API 的逻辑,创建一个 RequestTemplate,然后根据 RequestTemplate 获取对应的Request 记录日志,然后交由 client 执行,得到 response、decode 进行解码。

然后看下 Feign 中是如何集成 Hystrix,打开源码 FeignClientsConfiguration 类,在HystrixFeignConfiguration 对 Feign.Builder 进行了重新定义,返回的是 HystrixFeign.builder()

进入 HystrixFeign.builder 中可以看到继承了 Feign 的 Builder,增加了 Hystrix的SetterFactory

,看下 build 方法里,对 invocationHandlerFactory 进行了重写,在 create 的时候返回的是 HystrixInvocationHandler,HystrixInvocationHandler 中在 invoke 的时候会将请求包装成 HystrixCommand 去执行,这里就自然的集成了 Hystrix。

 

你可能感兴趣的:(微服务面试准备——Feign)