当前位置: 首页 > news >正文

Spring-Cloud-Loadblancer详细分析_1

背景

从SpringCloud 2020 版本之后,组件移除了除 Eureka 以外,所有 Netflix 的相关,包括最常用的 Ribbon Hystrix 等,所以 SpringCloud 在 spring-cloud-commons 提供了Loadbalancer 用来替代 Ribbon。本系列就来介绍Loadbalancer 的执行流程

项目版本:

  • Spring-Boot2.6.13
  • Spring-Cloud 2021.0.5
  • spring-cloud-alibaba 2021.0.5.0
  • Loadbalancer 3.1.5

从项目中最常用的Feign来当做入口,不了解Feign的原理也没有关系,直接从Feign和Loadbalancer 的集成部分分析即可

分析

入口处

FeignBlockingLoadBalancerClient

public class FeignBlockingLoadBalancerClient implements Client {private static final Log LOG = LogFactory.getLog(FeignBlockingLoadBalancerClient.class);private final Client delegate;private final LoadBalancerClient loadBalancerClient;private final LoadBalancerClientFactory loadBalancerClientFactory;@Overridepublic Response execute(Request request, Request.Options options) throws IOException {//请求路径final URI originalUri = URI.create(request.url());//获取到要调用的服务idString serviceId = originalUri.getHost();DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest<>(new RequestDataContext(buildRequestData(request), hint));	Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator.getSupportedLifecycleProcessors(//在这步创建了每个服务的子容器	loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),RequestDataContext.class, ResponseData.class, ServiceInstance.class);supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest));		//执行loadBalancer的负载均衡策略,返回将过滤后的服务,非常重要ServiceInstance instance = loadBalancerClient.choose(serviceId, lbRequest);org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse = new DefaultResponse(instance);//省略...//将ServiceInstance进行解析后,转换为真正的http方式进行远程调用服务String reconstructedUrl = loadBalancerClient.reconstructURI(instance, originalUri).toString();Request newRequest = buildRequest(request, reconstructedUrl);LoadBalancerProperties loadBalancerProperties = loadBalancerClientFactory.getProperties(serviceId);return executeWithLoadBalancerLifecycleProcessing(delegate, options, newRequest, lbRequest, lbResponse,supportedLifecycleProcessors, loadBalancerProperties.isUseRawStatusCodeInResponseData());}protected Request buildRequest(Request request, String reconstructedUrl) {return Request.create(request.httpMethod(), reconstructedUrl, request.headers(), request.body(),request.charset(), request.requestTemplate());}private String getHint(String serviceId) {LoadBalancerProperties properties = loadBalancerClientFactory.getProperties(serviceId);String defaultHint = properties.getHint().getOrDefault("default", "default");String hintPropertyValue = properties.getHint().get(serviceId);return hintPropertyValue != null ? hintPropertyValue : defaultHint;}}

可以看到,在OpenFeign中调用了loadBalancerClient.choose(serviceId, lbRequest)来实现负载均衡策略,然后返回过滤后的服务ServiceInstance,也就是服务的对象。我们要重点分析此过程

首先分析loadBalancerClient是怎么注入进来的呢,我们先看下其结构

ServiceInstanceChooser

public interface ServiceInstanceChooser {ServiceInstance choose(String serviceId);<T> ServiceInstance choose(String serviceId, Request<T> request);}

LoadBalancerClient

public interface LoadBalancerClient extends ServiceInstanceChooser {<T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;<T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException;URI reconstructURI(ServiceInstance instance, URI original);}

可以看到ServiceInstanceChooser定义了负载均衡的方法, LoadBalancerClient则继承了ServiceInstanceChooser额外定义了execute执行和reconstructURI构建真正http请求的方法

那么LoadBalancerClient的实现是谁呢,刚才的疑问中又是怎么被注入的呢,其实LoadBalancerClient的实现是BlockingLoadBalancerClient,在配置类BlockingLoadBalancerClientAutoConfiguration中被注入

这里既然提到了自动装配配置类,那么我们就需要看下其结构,来了解各个作用

# AutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerCacheAutoConfiguration,\
org.springframework.cloud.loadbalancer.security.OAuth2LoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerStatsAutoConfiguration
  • LoadBalancerAutoConfiguration 是最核心最重要的配置,随后会详细的分析
  • BlockingLoadBalancerClientAutoConfiguration 上文中提高的LoadBalancerClient的实现类BlockingLoadBalancerClient就是在此装配的

BlockingLoadBalancerClientAutoConfiguration

@Configuration(proxyBeanMethods = false)
@LoadBalancerClients
@AutoConfigureAfter(LoadBalancerAutoConfiguration.class)
@AutoConfigureBefore({ org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.class,AsyncLoadBalancerAutoConfiguration.class })
@ConditionalOnClass(RestTemplate.class)
public class BlockingLoadBalancerClientAutoConfiguration {@Bean@ConditionalOnBean(LoadBalancerClientFactory.class)@ConditionalOnMissingBeanpublic LoadBalancerClient blockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) {return new BlockingLoadBalancerClient(loadBalancerClientFactory);}//省略}

可以看到注入了LoadBalancerClient的实现类BlockingLoadBalancerClient。但此自动配置类的装配有很多的规则:

  1. @LoadBalancerClients 此注解非常重要,实现每个服务间的负载均衡配置隔离就是通过此注解,后面会详细的分析
  2. @AutoConfigureAfter(LoadBalancerAutoConfiguration.class)LoadBalancerAutoConfiguration之后进行装配,LoadBalancerAutoConfiguration也很重要,后面也会详细的分析
  3. @AutoConfigureBefore({ org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.class, AsyncLoadBalancerAutoConfiguration.class })org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfigurationAsyncLoadBalancerAutoConfiguration之前进行装配。注意:2和3中的LoadBalancerAutoConfiguration不是一个对象,2中的是在spring-cloud-loadbalancer模块中,3中的是在spring-cloud-commons模块中,这也是有步骤2的原因,毕竟肯定是要先装配本模块下的
  4. @ConditionalOnClass(RestTemplate.class)这个不是重点,可以略过
  5. @ConditionalOnBean(LoadBalancerClientFactory.class) 在注入时依赖了LoadBalancerClientFactoryLoadBalancerClientFactory也非常的重要,后面也会进行详细的分析

上面多次提到了LoadBalancerAutoConfiguration,自动装配中也有它,那么现在就来分析下其流程

LoadBalancerAutoConfiguration

@Configuration(proxyBeanMethods = false)
@LoadBalancerClients
@EnableConfigurationProperties(LoadBalancerClientsProperties.class)
@AutoConfigureBefore({ ReactorLoadBalancerClientAutoConfiguration.class,LoadBalancerBeanPostProcessorAutoConfiguration.class })
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.enabled", havingValue = "true", matchIfMissing = true)
public class LoadBalancerAutoConfiguration {//依赖了LoadBalancerClientSpecification类型的对象集合private final ObjectProvider<List<LoadBalancerClientSpecification>> configurations;public LoadBalancerAutoConfiguration(ObjectProvider<List<LoadBalancerClientSpecification>> configurations) {this.configurations = configurations;}@Bean@ConditionalOnMissingBeanpublic LoadBalancerZoneConfig zoneConfig(Environment environment) {return new LoadBalancerZoneConfig(environment.getProperty("spring.cloud.loadbalancer.zone"));}@ConditionalOnMissingBean@Beanpublic LoadBalancerClientFactory loadBalancerClientFactory(LoadBalancerClientsProperties properties) {LoadBalancerClientFactory clientFactory = new LoadBalancerClientFactory(properties);//LoadBalancerClientSpecification类型的配置类集合对象注入到NamedContextFactory,实现个性化配置clientFactory.setConfigurations(this.configurations.getIfAvailable(Collections::emptyList));return clientFactory;}}

可以看到此配置类的装配规则也比较复杂,但大部分都和本系列要分析的内容关联性不大,直接略过即可,我们只关心两个地方

  • @LoadBalancerClients 这个注解出现多次,我们会做详细的分析
  • 注入了loadBalancerClientFactory,这个也非常的重要,随后会做详细的分析

到这里我们要解决的三个重点:

  • @LoadBalancerClients的作用
  • ObjectProvider<List<LoadBalancerClientSpecification>> configurations的作用
  • LoadBalancerClientFactory的作用,别忘了负载均衡的执行对象BlockingLoadBalancerClient在生成时,将此对象注入了进去

下一篇文章我们进行详细分析

相关文章:

Spring-Cloud-Loadblancer详细分析_1

背景 从SpringCloud 2020 版本之后&#xff0c;组件移除了除 Eureka 以外&#xff0c;所有 Netflix 的相关&#xff0c;包括最常用的 Ribbon Hystrix 等&#xff0c;所以 SpringCloud 在 spring-cloud-commons 提供了Loadbalancer 用来替代 Ribbon。本系列就来介绍Loadbalance…...

键盘键码keyCode对照表

字母和数字键的键码值(KeyCode)按键键码按键键码A65J74B66K75C67L76D68M77E69N78F70O79G71P80H72Q81I73R82 字母和数字键的键码值(KeyCode)按键键码按键键码S83149T84250U85351V86452W87553X88654Y89755Z90856048957 数字键盘上的键的键码值(KeyCode)按键键码按键键码0968104…...

jupyter切换conda虚拟环境

环境安装 conda install nb_conda 进入你想使用的虚拟环境&#xff1a; conda activate your_env_name 在你想使用的conda虚拟环境中&#xff1a; conda install -y jupyter 在虚拟环境中安装jupyter&#xff1a; conda install -y jupyter 重启jupyter 此时我们已经把该安装…...

【数据结构•堆】经典问题:k路归并

题目描述 k路归并问题&#xff1a;   把k个有序表合并成一个有序表。&#xff08; k < 10^4 &#xff09; 输入输出格式 输入格式&#xff1a; 输入数据共有 2*k1 行。   第一行&#xff0c;一个整数k&#xff08; k < 10^4 &#xff09;&#xff0c;表示有k个有序…...

VUE3 动态路由

带参数的动态路由匹配 很多时候&#xff0c;我们需要将给定匹配模式的路由映射到同一个组件。例如&#xff0c;我们可能有一个 User 组件&#xff0c;它应该对所有用户进行渲染&#xff0c;但用户 ID 不同。在 Vue Router 中&#xff0c;我们可以在路径中使用一个动态字段来实现…...

CentOS软件包管理rpm、yum

一、软件包概述 Linux常见软件包分为两种&#xff0c;分别是源代码包、二进制文件包。源代码包是没有经过编译的包&#xff0c;需要经过GCC、C编译器编译才能运行&#xff0c;文件内容包含源代码文件&#xff0c;通常以.tar.gz、.zip、.rar结尾&#xff1b;二进制包无需编译&am…...

【VSCode】报错:出现段错误解决办法 (Segmentation fault)

VScode报错&#xff1a;Segmentation fault (core dumped)的解决办法 解决Program received signal SIGSEGV, Segmentation fault.的辛酸 Linux环境下段错误的产生原因及调试方法小结 Linux下的段错误Segmentationfault产生的原因及调试方法经典.pdf 在程序中&#xff0c;TF…...

Linux Centos 8 用户管理之重置密码

如果在使用linux系统时遇到系统密码问题无法进入系统或者操作的时候可以按照下面的方法重置用户密码。 一、root用户密码重置&#xff1a; 方式一&#xff1a; 1.重启电脑或虚拟机&#xff0c;在刚进引导界面时候按“e"键&#xff0c;进入编辑模式。 2.在”quiet"…...

C语言快速回顾(三)

前言 在Android音视频开发中&#xff0c;网上知识点过于零碎&#xff0c;自学起来难度非常大&#xff0c;不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》&#xff0c;结合我自己的工作学习经历&#xff0c;我准备写一个音视频系列blog。C/C是音视频必…...

【Apollo】Apollo-ros版本架构学习与源码分析

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍Apollo-ros版本架构学习与源码分析。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&a…...

【Express.js】集成RabbitMQ

集成RabbitMQ 本节我们介绍在 express.js 中集成 rabbitmq. RabbitMQ 是一个消息队列中间件&#xff0c;常用于请求削峰&#xff0c;事务的队列处理&#xff0c;事件订阅机制的实现等。 准备工作 创建一个 express.js 项目&#xff08;本文基于evp-express-cli&#xff09;…...

UI美工设计岗位的基本职责概述(合集)

UI美工设计岗位的基本职责概述1 1、有良好的美术功底、设计新颖&#xff0c;整体配色及设计创意理念&#xff0c;能够独立完成整个网站页面设计及制作; 2、熟练运用DIV CSS&#xff0c;HTML 设计制作网页 ; 3、熟练运用Photoshop,Dreamweaver,Coreldraw(或Illustrator),Fla…...

最强自动化测试框架Playwright(23)-API测试

playwright支持进行API测试 示例&#xff1a; 如下代码创建API请求上下文&#xff0c;使用post方法请求API&#xff0c;并返回响应结果。 import playwright from playwright.sync_api import sync_playwrightwith sync_playwright() as p:api_request_contextp.request.new…...

k8s 自身原理 4

前面咱们分享了 mater 和 worker 节点里面都有哪些组件&#xff0c;他们又是各自主要负责的工作是什么&#xff0c;现在我们心里应该都有数了吧 master 节点&#xff1a; etcd 存储资源配置&#xff0c;ApiServer 提供 RESTful Api 用于交互&#xff0c;scheduler 用于调度 p…...

ZLMediaKit(webrtc)在linux上(CentOS7)部署与启动

一.ZLMediaKit(webrtc)在CentOS7部署与启动 # 1. 卸载旧版本 yum remove git # 2. 安装 yum 源的 Git 版本 yum install -y git # 3. 查看版本 git version # 输出 git version 1.8.3.1配置全局环境变量 # 1. 编辑配置文件 vim /etc/profile # 2. 在 /etc/profile 文件中末尾…...

汽车基础软件新「战争」:群雄混战,谁在抢跑?

中国车用基础软件迎来了发展的黄金窗口期。 当前&#xff0c;汽车电子电气架构正在加速向“跨域融合”的时代演进&#xff0c;汽车软件架构也在加速向SOA架构升级&#xff0c;软硬件分层解耦成为了实现“软件定义汽车”新开发模式的前提。 过去&#xff0c;汽车的所有功能开发…...

阿里云预装LAMP应用导致MySQL不显示访问密码如何解决

&#x1f600;前言 本篇博文是关于阿里云云服务器ECS部署MySQL过程中出现的一下坑&#xff0c;希望能够帮助到您&#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家…...

SQL 自动清除7天前数据前收缩数据库

作用&#xff1a; 删除七天前数据库中间表的资料&#xff0c;并收缩数据库 delete-Ecustom-xml-midtable.sql delete Mid_bom where datediff(day,dty,getdate())>7 delete Mid_cus where datediff(day,dty,getdate())>7 delete Mid_exp where datediff(day,dty,getdate(…...

LangChain-ChatGLM在WIndows10下的部署

LangChain-ChatGLM在WIndows10下的部署 参考资料 1、LangChain ChatGLM2-6B 搭建个人专属知识库中的LangChain ChatGLM2-6B 构建知识库这一节&#xff1a;基本的逻辑和步骤是对的&#xff0c;但要根据Windows和现状做很多调整。 2、没有动过model_config.py中的“LORA_MOD…...

Telerik UI for ASP.NET Core Crack

Telerik UI for ASP.NET Core Crack Telerik ASP.NET Core还包括MVC和Kendo UI捆绑包(用于JavaScript)、Figma的设计工具包以及文档处理库、用于ASP.NET Core的Telerik REPL、RTL支持、辅助功能和键盘导航、主题化、虚拟课堂培训、详细文档、演示、KBs和世界级支持。使用一整套…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...