Spring-Cloud-Loadblancer详细分析_4
在RoundRobinLoadBalancer.choose
中的serviceInstanceListSupplierProvider
就是获取服务列表的关键,那么此对象是怎么拿到的呢,让我们回到RoundRobinLoadBalancer
的创建过程
@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
public class LoadBalancerClientConfiguration {private static final int REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER = 193827465;/*** 轮训的负载均衡策略*/@Bean@ConditionalOnMissingBeanpublic ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RoundRobinLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);}/*** WebFlux环境下的ServiceInstanceListSupplier的bean*/@Configuration(proxyBeanMethods = false)@ConditionalOnReactiveDiscoveryEnabled@Order(REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER)public static class ReactiveSupportConfiguration {@Bean@ConditionalOnBean(ReactiveDiscoveryClient.class)@ConditionalOnMissingBean@Conditional(DefaultConfigurationCondition.class)public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {return ServiceInstanceListSupplier.builder().withDiscoveryClient().withCaching().build(context);}//省略 }/*** web环境的ServiceInstanceListSupplier的bean*/@Configuration(proxyBeanMethods = false)@ConditionalOnBlockingDiscoveryEnabled@Order(REACTIVE_SERVICE_INSTANCE_SUPPLIER_ORDER + 1)public static class BlockingSupportConfiguration {@Bean@ConditionalOnBean(DiscoveryClient.class)@ConditionalOnMissingBean@Conditional(DefaultConfigurationCondition.class)public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withCaching().build(context);}}//省略
}
可以看都是在LoadBalancerClientConfiguration
中配置的,可见此配置类的重要程度
web环境的加载就是BlockingSupportConfiguration
下的discoveryClientServiceInstanceListSupplier
@Bean
@ConditionalOnBean(DiscoveryClient.class)
@ConditionalOnMissingBean
@Conditional(DefaultConfigurationCondition.class)
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {return ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withCaching().build(context);
}
调用了ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withCaching().build(context)
来创建ServiceInstanceListSupplier
。这一行有多个方法,我们逐个分析
ServiceInstanceListSupplier
public interface ServiceInstanceListSupplier extends Supplier<Flux<List<ServiceInstance>>> {String getServiceId();default Flux<List<ServiceInstance>> get(Request request) {return get();}static ServiceInstanceListSupplierBuilder builder() {return new ServiceInstanceListSupplierBuilder();}}
提供了builder
方法返回 ServiceInstanceListSupplierBuilder
实例
ServiceInstanceListSupplierBuilder
public final class ServiceInstanceListSupplierBuilder {private static final Log LOG = LogFactory.getLog(ServiceInstanceListSupplierBuilder.class);private Creator baseCreator;private DelegateCreator cachingCreator;private final List<DelegateCreator> creators = new ArrayList<>();ServiceInstanceListSupplierBuilder() {}/*** Sets a blocking {@link DiscoveryClient}-based* {@link DiscoveryClientServiceInstanceListSupplier} as a base* {@link ServiceInstanceListSupplier} in the hierarchy.* @return the {@link ServiceInstanceListSupplierBuilder} object*/public ServiceInstanceListSupplierBuilder withBlockingDiscoveryClient() {if (baseCreator != null && LOG.isWarnEnabled()) {LOG.warn("Overriding a previously set baseCreator with a blocking DiscoveryClient baseCreator.");}this.baseCreator = context -> {//获取注册中心的操作对象 discoveryClient DiscoveryClient discoveryClient = context.getBean(DiscoveryClient.class);return new DiscoveryClientServiceInstanceListSupplier(discoveryClient, context.getEnvironment());};return this;}/*** If {@link LoadBalancerCacheManager} is available in the context, wraps created* {@link ServiceInstanceListSupplier} hierarchy with a* {@link CachingServiceInstanceListSupplier} instance to provide a caching mechanism* for service instances. Uses {@link ObjectProvider} to lazily resolve* {@link LoadBalancerCacheManager}.* @return the {@link ServiceInstanceListSupplierBuilder} object*/public ServiceInstanceListSupplierBuilder withCaching() {if (cachingCreator != null && LOG.isWarnEnabled()) {LOG.warn("Overriding a previously set cachingCreator with a CachingServiceInstanceListSupplier-based cachingCreator.");}this.cachingCreator = (context, delegate) -> {ObjectProvider<LoadBalancerCacheManager> cacheManagerProvider = context.getBeanProvider(LoadBalancerCacheManager.class);if (cacheManagerProvider.getIfAvailable() != null) {return new CachingServiceInstanceListSupplier(delegate, cacheManagerProvider.getIfAvailable());}if (LOG.isWarnEnabled()) {LOG.warn("LoadBalancerCacheManager not available, returning delegate without caching.");}return delegate;};return this;}/*** Builds the {@link ServiceInstanceListSupplier} hierarchy.* @param context application context* @return a {@link ServiceInstanceListSupplier} instance on top of the delegate* hierarchy*/public ServiceInstanceListSupplier build(ConfigurableApplicationContext context) {Assert.notNull(baseCreator, "A baseCreator must not be null");ServiceInstanceListSupplier supplier = baseCreator.apply(context);for (DelegateCreator creator : creators) {supplier = creator.apply(context, supplier);}if (this.cachingCreator != null) {supplier = this.cachingCreator.apply(context, supplier);}return supplier;}//省略
}
在调用withBlockingDiscoveryClient()
方法,内部调用了new DiscoveryClientServiceInstanceListSupplier(discoveryClient, context.getEnvironment())
DiscoveryClientServiceInstanceListSupplier
public class DiscoveryClientServiceInstanceListSupplier implements ServiceInstanceListSupplier {/*** Property that establishes the timeout for calls to service discovery.*/public static final String SERVICE_DISCOVERY_TIMEOUT = "spring.cloud.loadbalancer.service-discovery.timeout";private static final Log LOG = LogFactory.getLog(DiscoveryClientServiceInstanceListSupplier.class);private Duration timeout = Duration.ofSeconds(30);private final String serviceId;private final Flux<List<ServiceInstance>> serviceInstances;public DiscoveryClientServiceInstanceListSupplier(DiscoveryClient delegate, Environment environment) {this.serviceId = environment.getProperty(PROPERTY_NAME);resolveTimeout(environment);//delegate.getInstances(serviceId)就是从注册中心拉取服务列表了,//然后赋给serviceInstances this.serviceInstances = Flux.defer(() -> Mono.fromCallable(() -> delegate.getInstances(serviceId))).timeout(timeout, Flux.defer(() -> {logTimeout();return Flux.just(new ArrayList<>());}), Schedulers.boundedElastic()).onErrorResume(error -> {logException(error);return Flux.just(new ArrayList<>());});}//省略@Overridepublic String getServiceId() {return serviceId;}@Overridepublic Flux<List<ServiceInstance>> get() {return serviceInstances;}private void resolveTimeout(Environment environment) {String providedTimeout = environment.getProperty(SERVICE_DISCOVERY_TIMEOUT);if (providedTimeout != null) {timeout = DurationStyle.detectAndParse(providedTimeout);}}private void logTimeout() {if (LOG.isDebugEnabled()) {LOG.debug(String.format("Timeout occurred while retrieving instances for service %s."+ "The instances could not be retrieved during %s", serviceId, timeout));}}private void logException(Throwable error) {if (LOG.isErrorEnabled()) {LOG.error(String.format("Exception occurred while retrieving instances for service %s", serviceId), error);}}}
然后就来到了withCaching()
public ServiceInstanceListSupplierBuilder withCaching() {if (cachingCreator != null && LOG.isWarnEnabled()) {LOG.warn("Overriding a previously set cachingCreator with a CachingServiceInstanceListSupplier-based cachingCreator.");}this.cachingCreator = (context, delegate) -> {ObjectProvider<LoadBalancerCacheManager> cacheManagerProvider = context.getBeanProvider(LoadBalancerCacheManager.class);if (cacheManagerProvider.getIfAvailable() != null) {return new CachingServiceInstanceListSupplier(delegate, cacheManagerProvider.getIfAvailable());}if (LOG.isWarnEnabled()) {LOG.warn("LoadBalancerCacheManager not available, returning delegate without caching.");}return delegate;};return this;
}
build(context)
进行构建
public ServiceInstanceListSupplier build(ConfigurableApplicationContext context) {Assert.notNull(baseCreator, "A baseCreator must not be null");ServiceInstanceListSupplier supplier = baseCreator.apply(context);for (DelegateCreator creator : creators) {supplier = creator.apply(context, supplier);}if (this.cachingCreator != null) {supplier = this.cachingCreator.apply(context, supplier);}return supplier;
}
相关文章:
Spring-Cloud-Loadblancer详细分析_4
在RoundRobinLoadBalancer.choose中的serviceInstanceListSupplierProvider就是获取服务列表的关键,那么此对象是怎么拿到的呢,让我们回到RoundRobinLoadBalancer的创建过程 Configuration(proxyBeanMethods false) ConditionalOnDiscoveryEnabled pub…...

openocd调试esp32(通过FT232H)
之前在学习ESP32,其中有一部分课程是学习openocd通过JTAG调试程序的,因为我用的是ESP32-wroom,usb端口没有集成对应的usb转jtag的ft232,查了ESP32相关的资料(JTAG 调试 - ESP32 - — ESP-IDF 编程指南 latest 文档 (es…...
Nokia5110使用方法及实例编写51单片机
文章目录 Nokia5110实物图引脚和原理图51单片机实例软件模拟SPI实现控制Nokia5110显示字符发送字节时序图(图片太多了,关键图片已截取出来)初始化需要配置实例编写回顾接线结束Nokia5110 Nokia是诺基亚拆下来的屏幕。使用SPI控制 84x48 的点阵 LCD,可以显示 4 行汉字,采用…...

3个月快速入门LoRa物联网传感器开发
在这里插入图片描述 快速入门LoRa物联网传感器开发 LoRa作为一种LPWAN(低功耗广域网络)无线通信技术,非常适合物联网传感器和行业应用。要快速掌握LoRa开发,需要系统学习理论知识,并通过实际项目积累经验。 摘要: 先学习LoRa基础知识:原理、网络架构、协议等,大概需要2周时间…...

【小梦C嘎嘎——启航篇】内存管理小知识~
【小梦C嘎嘎——启航篇】内存管理小知识~😎 前言🙌malloc/calloc/realloc的区别?new 与 deletenew与delete要找好搭档才能保证万无一失 new 与 delete的内部实现细节是怎么样的呢???new 的内部实现细节dele…...
ClickHouse查看执行计划(EXPLAIN语法)
1.EXPLAIN 语法示例 EXPLAIN [AST | SYNTAX | QUERY TREE | PLAN | PIPELINE | ESTIMATE | TABLE OVERRIDE] [setting value, ...] [ SELECT ... | tableFunction(...) [COLUMNS (...)] [ORDER BY ...] [PARTITION BY ...] [PRIMARY KEY] [SAMPLE BY ...] [T…...

线程池
线程池 什么是线程池? 想象一下 假设我是个漂亮妹子,这时候接受了舔狗A的表白,随着时间的推移,逐渐不喜欢A这小子了,于是我就想换个男朋友,可是 1.处理分手,需要消耗一定成本 2.再找一个新对象…...

配置:Terminal和oh-my-posh
目录 命令行安装oh-my-posh查看安装情况配置PowerShell启用oh-my-posh、设置主题配色安装字体Terminal中的配置 命令行安装oh-my-posh Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString(https://ohmy…...

数据结构--BFS求最短路
数据结构–BFS求最短路 BFS求⽆权图的单源最短路径 注:⽆权图可以视为⼀种特殊的带权图,只是每条边的权值都为1 以 2 为 b e g i n 位置 以2为begin位置 以2为begin位置 代码实现 //求顶点u到其他顶点的最短路径 void BFS_MIN_Distance(Graph G, int u…...

FPGA应用学习笔记----定点除法的gold算法流水线设计
猜一个Y0 a和b上下都Y0 分母越接近一,分子就越接近答案 误差: 下一步迭代为 Y的迭代值: 误差值: 代码的实现如上所示...
Nginx转发的原理和负载均衡
一、Nginx转发的原理 Nginx是一个高性能的反向代理服务器,它可以用于实现请求的转发和负载均衡。以下是Nginx转发的基本原理: 客户端发送请求:客户端向Nginx服务器发送HTTP请求。 Nginx接收请求:Nginx服务器接收到客户端的请求。…...
怎么换ip地址 电脑切换ip地址方法
互联网时代,IP地址是我们在网络上进行通信和访问的身份标识。有时候,我们可能需要更改IP地址,以便获得更好的网络体验或绕过某些限制。本文将介绍如何使用深度IP转换器来更改IP地址。 1:了解IP地址 IP地址是一个由数字和点组成的标…...
软件设计基础
巩固基础,砥砺前行 。 只有不断重复,才能做到超越自己。 能坚持把简单的事情做到极致,也是不容易的。 软件项目管理。 在经历了软件危机和大连的软件项目失败以后,人们对软件工程专业的现状进行了多次分析。得出了普遍性的结论&…...
OptaPlanner笔记5
2.4 与spring boot集成 2.4.4 添加依赖 <dependency><groupId>org.optaplanner</groupId><artifactId>optaplanner-spring-boot-starter</artifactId> </dependency>2.4.8 创建求解器服务 import org.optaplanner.core.api.solver.Solv…...
PS注意事项优漫动游
PS入门注意事项AdobePhotoshop是目前最流行的平面设计软件之一。可以说,只要你接触平面设计,那么无论早晚,你都要和它打交道。关于Photoshop,要说的实在太多太多,但不论你想让它成为你的左膀右臂,或者仅仅是…...
matplotlib 判断鼠标是否点击在当前线上
在开发中有一个需求:对生成的一条线进行拖拽。 我将这个方法实现在线所在的类里,这个过程中需要判断鼠标是否点击在当前线上,从而实现拖拽。 实现代码如下: # 点击事件 def on_press(self,event):if event.inaxes ! self.ax:retur…...
bash中(冒号破折号)的用法 —— 筑梦之路
${PUBLIC_INTERFACE:-eth0} :- 的用途是什么? 含义:如果 $PUBLIC_INTERFACE 存在且不是 null,则返回其值,否则返回 "eth0"。 ${parameter:-word} 使用默认值。如果 parameter 未设置或为 null,则 word 的扩…...

LeetCode150道面试经典题--同构字符串(简单)
1.题目 给定两个字符串 s 和 t ,判断它们是否是同构的。如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,…...

Redis - 数据类型映射底层结构
简介 从数据类型上体现就是,同一个数据类型,在不同的情况下会使用不同的编码类型,底层所使用的的数据结构也不相同。 字符串对象 字符串对象的编码可以是 int、raw 和 embstr 三者之一。 embstr 编码是专门用于保存简短字符串的一种优化编…...

MySQL数据库表的增删查改 - 进阶
一,数据库约束 1.1 约束对象 not null - 该列不能为空unique - 保证该列的每一行都不一样default - 规定没有给列赋值时的默认值(自定义)primary key - not null 和 unique 的结合,会给该列添加一个索引࿰…...

Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...