当前位置:网站首页>[Cloud native] Ribbon is no longer used at the bottom layer of OpenFeign starting from the 2020.0.X version
[Cloud native] Ribbon is no longer used at the bottom layer of OpenFeign starting from the 2020.0.X version
2022-07-31 05:53:00 【m0_67392811】
文章目录
一、前言
在前面的Feign系列文章:
- SpringCloud之Feign实现声明式客户端负载均衡详细案例
- SpringCloud之OpenFeign实现服务间请求头数据传递(OpenFeign拦截器RequestInterceptor的使用)
- SpringCloud之OpenFeign的常用配置(超时、数据压缩、日志)
- SpringCloud之OpenFeign的核心组件(Encoder、Decoder、Contract)
- SpringBoot启动流程中开启OpenFeign的入口(ImportBeanDefinitionRegistrar详解)
- 源码剖析OpenFeign如何扫描所有的FeignClient
- 源码剖析OpenFeign如何为FeignClient生成动态代理类
- 图文源码剖析OpenFeign处理请求流程
我们聊了以下内容:
- OpenFeign的概述、为什么会使用Feign代替Ribbon
- Feign和OpenFeign的区别
- 详细的OpenFeign实现声明式客户端负载均衡案例
- OpenFeign中拦截器RequestInterceptor的使用
- OpenFeign的一些常用配置(超时、数据压缩、日志输出)
- SpringCloud之OpenFeign的核心组件(Encoder、Decoder、Contract)
- 在SpringBoot启动流程中开启OpenFeign的入口
- OpenFeign如何扫描 / 注册所有的FeignClient
- OpenFeign如何为FeignClient生成动态代理类
- OpenFeign处理请求流程
本文基于OpenFeign高版本(SpringCloud 2020.0.x版本开始之后的版本)讨论:OpenFeign新版本和旧版本之间的差异(高版本OpenFeign底层不使用Ribbon做负载均衡)
PS:本文使用的SpringCloud高版本:
<properties>
<spring-boot.version>2.4.2</spring-boot.version>
<spring-cloud.version>2020.0.1</spring-cloud.version>
<spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--整合spring cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--整合spring cloud alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
PS:本文使用的SpringCloud低版本:
<properties>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.6.RELEASE</spring-cloud-alibaba.version>
</properties>
二、源码主流程版本间差异串讲
1、@FeignClientsRegistrar开启对FeignClient的扫描
此处主流程上无区别;
在SpringBoot启动流程中@FeignClientsRegistrar注解开启OpenFeign的入口、OpenFeign扫描所有的FeignClient的流程 高版本和低版本基本一样,低版本的见文章:[这里是代码005]注解开启OpenFeign的入口、OpenFeign扫描所有的FeignClient.
主要流程如下:
1> 开启扫描FeignClient的入口:
- 启动类上添加的
@EnableFeignClients注解会通过@Import注解在SpringBoot启动流程中将ImportBeanDefinitionRegistrar接口的实现类FeignClientsRegistrar注入到启动类的ConfigurationClass的属性中,在注册启动类的BeanDefinition时,会遍历调用其@Import的所有ImportBeanDefinitionRegistrar接口的 registerBeanDefinitions()方法.2> 扫描FeignClient:
- 拿到@EnableFeignClients注解中配置的扫描包路径相关的属性,得到要扫描的包路径;
- 获取到扫描器
ClassPathScanningCandidateComponentProvider,然后给其添加一个注解过滤器(AnnotationTypeFilter),只过滤出包含@FeignClient注解的BeanDefinition;- 扫描器的findCandidateComponents(basePackage)方法从包路径下扫描出所有标注了@FeignClient注解并符合条件装配的接口;然后将其在BeanDefinitionRegistry中注册一下;
2、为FeignClient生成动态代理类
区别主要体现在这里;
在注册FeignClient到Spring容器时,构建的BeanDefinition的beanClas是FeignClientFactoryBean;FeignClientFactoryBean是一个工厂,保存了@FeignClient注解的所有属性值,在Spring容器初始化的过程中,其会根据之前扫描出的FeignClient信息构建FeignClient的动态代理类.
具体的动态代理类生成流程参考博文:OpenFeign如何为FeignClient生成动态代理类;
底层通信Client的区别?
在使用Feign.Builder构建FeignClient的时候,获取到的Client是FeignBlockingLoadBalancerClient(这其中的逻辑后面聊,在OpenFeign低版本是LoadBalancerFeignClient);用于生成FeignClient的Targeter是DefaultTargeter(在OpenFeign低版本是HystrixTargeter,高版本移除了Hystrix,采用Spring Cloud Circuit Breaker 做限流熔断);
具体体现在FeignClientFactoryBean#loadBalance()方法,其是一个进行负载均衡的FeignClient动态代理生成方法;
OpenFeign低版本:
1> FeignBlockingLoadBalancerClient何时注入到Spring容器?
FeignBlockingLoadBalancerClient注入到Spring容器的方式和OpenFeign低版本的LoadBalancerFeignClient是一样的;
进入到FeignBlockingLoadBalancerClient类中,看哪里调用了它唯一一个构造函数;

找到FeignBlockingLoadBalancerClient发现有三个地方调用了它的构造函数,new了一个实例;
- DefaultFeignLoadBalancedConfiguration
- HttpClientFeignLoadBalancedConfiguration
- OkHttpFeignLoadBalancedConfiguration
再结合默认的配置,只有DefaultFeignLoadBalancedConfiguration中的Client符合条件装配;

可以通过引入Apache HttpClient的maven依赖使用HttpClientFeignLoadBalancedConfiguration,
或引入OkHttpClient的maven依赖并在application.yml文件中指定feign.okhttp.enabled属性为true使用OkHttpFeignLoadBalancedConfiguration.
2> DefaultTargeter在哪里注入到Spring容器?
DefaultTargeter注入到Spring容器的方式和OpenFeign低版本的HystrixTargeter是一样的;
在FeignAutoConfiguration类中可以找到Targeter注入到Spring容器的逻辑;

3> 后续生成动态代理类的逻辑和旧版本一样
都体现在ReflectiveFeign#newInstance()方法中:

3、**Client处理负载均衡(核心区别)
上面提到OpenFeign高版本获取到的Client是FeignBlockingLoadBalancerClient,而低版本的是LoadBalancerFeignClient,LoadBalancerFeignClient基于Ribbon实现负载均衡,FeignBlockingLoadBalancerClient就靠OpenFeign自己实现负载均衡;
OpenFeign如何处理一个HTTP请求见博文:图文源码剖析OpenFeign处理请求流程.
接下来浅看一下FeignBlockingLoadBalancerClient是如何做负载均衡的!!
1)FeignBlockingLoadBalancerClient选择一个服务实例

先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在.深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小.自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前.因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担.添加下方名片,即可获取全套学习资料哦
边栏推荐
猜你喜欢

详解扫雷游戏(C语言)

DeFi 项目中的治理Token

MySQL-如何分库分表?一看就懂

If the account number or password is entered incorrectly for many times, the account will be banned.

阿里云中mysql数据库被攻击了,最终数据找回来了

On the side of Ali, tell me what are the application scenarios of message middleware you know?

NFT:数字所有权的核心
Getting to know regular expressions
uni-app进阶之自定义【day13】

Redis管道技术/分区
随机推荐
DeFi 项目中的治理Token
The MySQL database in Alibaba Cloud was attacked, and the data was finally recovered
继承、Super,重写、抽象类、抽象方法 1(第七天)
wpf ScrowViewer水平滚动
【C语言3个基本结构详解——顺序、选择、循环】
Access数据库的查询
vulhub靶场学习日记hackme2
leetcode-每日一题558. 四叉树交集(分治递归)
C language tutorial (2) - printf and data types that come with c
gin框架学习-Gin框架和Gorm框架搭建一个简单的API微服务
leetcode-每日一题剑指 Offer II 041. 滑动窗口的平均值(队列模拟)
利用phpstudy搭建DVWA
字符串的扩展
Sword Point Offer Special Assault Edition ---- Day 2
leetcode-829. 连续整数求和(数论)
局部变量成员变量、引用类型、this,static(第五天)
Linux中mysql密码修改方法(亲测可用)
初识正则表达式
feign调用不通问题,JSON parse error Illegal character ((CTRL-CHAR, code 31)) only regular white space (r
leetcode-每日一题735. 行星碰撞(栈模拟)