Ribbon、Feign与OpenFeign
Ribbon
Ribbon是 Netflix 开源的基于 HTTP 和 TCP 等协议负载均衡组件
Ribbon可以用来做客户端负载均衡,调用注册中心的服务
Ribbon的使用需要代码里手动调用目标服务(RestTemplate等)
Feign
Feign是 Spring Cloud 组件中的一个轻量级 RESTful
的HTTP服务客户端
Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务
Feign的使用方式是:使用 Feign 的注解定义接口,调用这个接口,就可以调用服务注册中心的服务
Feign本身不支持 Spring MVC 的注解,它有一套自己的注解
OpenFeign
OpenFeign是 Spring Cloud 在 Feign 的基础上支持了 Spring MVC 的注解
OpenFeign的 @FeignClient
可以解析 SpringMVC 的 @RequestMapping
注解下的接口
并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务
OpenFeign工作原理
Feign调用的编码流程
- pom.xml文件中添加了 Spring Cloud OpenFeign 的依赖
- 在 SpringBoot 主启动类上添加了注解
@EnableFeignCleints
- 定义接口
PaymentService
, 添加@FeignClient
注解 - 在需要使用 Feign 接口 PaymentService 的地方, 直接利用 @Resource 进行注入
- 使用接口完成对服务端微服务的调用
整体的工作流程分析
- SpringBoot主启动类启动时, 由针对
@EnableFeignClient
这一注解的处理程序扫描 classPath 下所有被@FeignClient
注解的类, 这里以PaymentService
为例, 将这些类解析为 BeanDefinition 注册到 Spring 容器中 - IOC容器在为某些用的 Feign 接口的 Bean 注入
PaymentService
时, Spring 会尝试从容器中查找 PaymentService 的实现类 - 由于我们从来没有编写过
PaymentService
的实现类, 上面步骤获取到的 PaymentService 的实现类必然是 feign 框架通过扩展 spring 的 Bean 处理逻辑, 为PaymentService
创建一个动态接口代理对象, 这里我们将其称为PaymentServiceProxy
注册到spring 容器中 - Spring最终在使用到
PaymentService
的 Bean 中注入了PaymentServiceProxy
实例 - 当业务请求真实发生时, 对于
PaymentService
的调用被统一转发到了由 Feign 框架实现的InvocationHandler
中,InvocationHandler
负责将接口中的入参转换为 HTTP 的形式,通过RestTemplate
发到服务端, 最后再解析 HTTP 响应, 将结果转换为 Java 对象予以返回 - 核心就是通过一系列的封装和处理,将以 JAVA 注解的方式定义的远程调用 API 接口,最终转换成 HTTP 的请求形式,然后将 HTTP 的请求的响应结果,解码成 JAVA Bean,返回给调用者
一段话总结:在微服务启动时,Feign会进行包扫描,对加@FeignClient注解的接口,按照注解的规则,创建远程接口的本地JDK Proxy代理实例。然后,将这些本地Proxy代理实例,注入到Spring IOC容器中。当远程接口的方法被调用,由Proxy代理实例去完成真正的远程访问,并且返回结果
远程接口的本地JDK Proxy代理实例
- Proxy代理实例,实现了一个加 @FeignClient 注解的远程调用接口
- Proxy代理实例,能在内部进行HTTP请求的封装,以及发送HTTP 请求
- Proxy代理实例,能处理远程HTTP请求的响应,并且完成结果的解码,然后返回给调用者
OpenFeign超时控制
OpenFeign默认等待一秒钟,但是服务端处理需要超过一秒钟,导致Feign客户端不想等待了,直接返回报错。为了避免这种情况,有时候我们需要设置Feign客户端的超时控制
在YML文件中开启OpenFeign客户端超时控制
#设置 feign 客户端超时时间(openFeign默认支持ribbon)
ribbon:
ReadTimeout: 5000 #指的是建立连接后从服务器读取到可用资源的时间
ConnectTimeout: 5000 #指的是建立连接所用的时间,适用于网络状态正常的情况下,两端连接所用的时间
OpenFeign日志打印
Feign提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解Feign中HTTP请求的细节
就是对Feign接口的调用情况进行监控和输出
日志级别
NONE:默认的,不显示任何日志
BASIC:仅记录请求方法、URL、响应状态码及执行时间
HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息
FULL:除了BASIC中定义的信息之外,还有请求和响应的正文及元数据
配置日志Bean
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
YAML文件里开启
logging:
level:
com.service.PaymentFeignService: debug # feign日志以什么级别监控哪个接口