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

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就是获取服务列表的关键&#xff0c;那么此对象是怎么拿到的呢&#xff0c;让我们回到RoundRobinLoadBalancer的创建过程 Configuration(proxyBeanMethods false) ConditionalOnDiscoveryEnabled pub…...

openocd调试esp32(通过FT232H)

之前在学习ESP32&#xff0c;其中有一部分课程是学习openocd通过JTAG调试程序的&#xff0c;因为我用的是ESP32-wroom&#xff0c;usb端口没有集成对应的usb转jtag的ft232&#xff0c;查了ESP32相关的资料&#xff08;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嘎嘎——启航篇】内存管理小知识~&#x1f60e; 前言&#x1f64c;malloc/calloc/realloc的区别&#xff1f;new 与 deletenew与delete要找好搭档才能保证万无一失 new 与 delete的内部实现细节是怎么样的呢&#xff1f;&#xff1f;&#xff1f;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…...

线程池

线程池 什么是线程池&#xff1f; 想象一下 假设我是个漂亮妹子&#xff0c;这时候接受了舔狗A的表白&#xff0c;随着时间的推移&#xff0c;逐渐不喜欢A这小子了&#xff0c;于是我就想换个男朋友&#xff0c;可是 1.处理分手&#xff0c;需要消耗一定成本 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求⽆权图的单源最短路径 注&#xff1a;⽆权图可以视为⼀种特殊的带权图&#xff0c;只是每条边的权值都为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 分母越接近一&#xff0c;分子就越接近答案 误差&#xff1a; 下一步迭代为 Y的迭代值&#xff1a; 误差值&#xff1a; 代码的实现如上所示...

Nginx转发的原理和负载均衡

一、Nginx转发的原理 Nginx是一个高性能的反向代理服务器&#xff0c;它可以用于实现请求的转发和负载均衡。以下是Nginx转发的基本原理&#xff1a; 客户端发送请求&#xff1a;客户端向Nginx服务器发送HTTP请求。 Nginx接收请求&#xff1a;Nginx服务器接收到客户端的请求。…...

怎么换ip地址 电脑切换ip地址方法

互联网时代&#xff0c;IP地址是我们在网络上进行通信和访问的身份标识。有时候&#xff0c;我们可能需要更改IP地址&#xff0c;以便获得更好的网络体验或绕过某些限制。本文将介绍如何使用深度IP转换器来更改IP地址。 1&#xff1a;了解IP地址 IP地址是一个由数字和点组成的标…...

软件设计基础

巩固基础&#xff0c;砥砺前行 。 只有不断重复&#xff0c;才能做到超越自己。 能坚持把简单的事情做到极致&#xff0c;也是不容易的。 软件项目管理。 在经历了软件危机和大连的软件项目失败以后&#xff0c;人们对软件工程专业的现状进行了多次分析。得出了普遍性的结论&…...

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是目前最流行的平面设计软件之一。可以说&#xff0c;只要你接触平面设计&#xff0c;那么无论早晚&#xff0c;你都要和它打交道。关于Photoshop&#xff0c;要说的实在太多太多&#xff0c;但不论你想让它成为你的左膀右臂&#xff0c;或者仅仅是…...

matplotlib 判断鼠标是否点击在当前线上

在开发中有一个需求&#xff1a;对生成的一条线进行拖拽。 我将这个方法实现在线所在的类里&#xff0c;这个过程中需要判断鼠标是否点击在当前线上&#xff0c;从而实现拖拽。 实现代码如下&#xff1a; # 点击事件 def on_press(self,event):if event.inaxes ! self.ax:retur…...

bash中(冒号破折号)的用法 —— 筑梦之路

${PUBLIC_INTERFACE:-eth0} :- 的用途是什么&#xff1f; 含义&#xff1a;如果 $PUBLIC_INTERFACE 存在且不是 null&#xff0c;则返回其值&#xff0c;否则返回 "eth0"。 ${parameter:-word} 使用默认值。如果 parameter 未设置或为 null&#xff0c;则 word 的扩…...

LeetCode150道面试经典题--同构字符串(简单)

1.题目 给定两个字符串 s 和 t &#xff0c;判断它们是否是同构的。如果 s 中的字符可以按某种映射关系替换得到 t &#xff0c;那么这两个字符串是同构的。每个出现的字符都应当映射到另一个字符&#xff0c;同时不改变字符的顺序。不同字符不能映射到同一个字符上&#xff0c…...

Redis - 数据类型映射底层结构

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

MySQL数据库表的增删查改 - 进阶

一&#xff0c;数据库约束 1.1 约束对象 not null - 该列不能为空unique - 保证该列的每一行都不一样default - 规定没有给列赋值时的默认值&#xff08;自定义&#xff09;primary key - not null 和 unique 的结合&#xff0c;会给该列添加一个索引&#xff0…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

k8s从入门到放弃之HPA控制器

k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率&#xff08;或其他自定义指标&#xff09;来调整这些对象的规模&#xff0c;从而帮助应用程序在负…...

绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化

iOS 应用的发布流程一直是开发链路中最“苹果味”的环节&#xff1a;强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说&#xff0c;这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发&#xff08;例如 Flutter、React Na…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码&#xff1a;冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...

云安全与网络安全:核心区别与协同作用解析

在数字化转型的浪潮中&#xff0c;云安全与网络安全作为信息安全的两大支柱&#xff0c;常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异&#xff0c;并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全&#xff1a;聚焦于保…...