Spring Cloud LoadBalancer 4.1.2

2024-05-11 07:04

本文主要是介绍Spring Cloud LoadBalancer 4.1.2,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

LoadBalancer位于Spring Cloud Commons 模块

Spring Cloud 提供了自己的客户端负载均衡器抽象和实现。对于负载均衡机制,添加了 ReactiveLoadBalancer 接口,并为其提供了基于Round-Robin和Random的实现。为了让实例从反应式中进行选择,使用了 ServiceInstanceListSupplier 。目前,我们支持基于服务发现的 ServiceInstanceListSupplier 实现,它使用类路径中提供的发现客户端从服务发现中检索可用实例。

可以通过将 spring.cloud.loadbalancer.enabled 的值设置为 false 来禁用 Spring Cloud LoadBalancer。

Spring Cloud LoadBalancer 入门

我们提供了一个启动器,允许您在 Spring Boot 应用程序中轻松添加 Spring Cloud LoadBalancer。为了使用它,只需将 org.springframework.cloud:spring-cloud-starter-loadbalancer 添加到构建文件中的 Spring Cloud 依赖项中。

传递您自己的 Spring Cloud LoadBalancer 配置

您还可以使用 @LoadBalancerClient 注释来传递您自己的负载均衡器客户端配置,传递负载均衡器客户端的名称和配置类,如下所示:

@Configuration
@LoadBalancerClient(//下面的value值大小写一定要和consul里面的名字一样,必须一样value = "cloud-payment-service",configuration = RestTemplateConfig.class)
public class RestTemplateConfig
{//使用的是RestTemplate@Bean@LoadBalanced //使用@LoadBalanced注解赋予RestTemplate负载均衡的能力public RestTemplate restTemplate(){return new RestTemplate();}//这里使用的是webClient@Bean@LoadBalancedpublic WebClient.Builder loadBalancedWebClientBuilder() {return WebClient.builder();}@BeanReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);}
}

为了使您自己的 LoadBalancer 配置更容易,我们在 ServiceInstanceListSupplier 类中添加了 builder() 方法。

您还可以使用我们的替代预定义配置来代替默认配置,方法是将 spring.cloud.loadbalancer.configurations 属性的值设置为 zone-preference 以使用 ZonePreferenceServiceInstanceListSupplier 进行缓存或设置为 health-check 将 HealthCheckServiceInstanceListSupplier 与缓存一起使用。

您还可以通过 @LoadBalancerClients 注释传递多个配置(针对多个负载均衡器客户端),如以下示例所示:

@Configuration
@LoadBalancerClients({@LoadBalancerClient(value = "stores", configuration = StoresLoadBalancerClientConfiguration.class), @LoadBalancerClient(value = "customers", configuration = CustomersLoadBalancerClientConfiguration.class)})
public class MyConfiguration {@Bean@LoadBalancedpublic WebClient.Builder loadBalancedWebClientBuilder() {return WebClient.builder();}
}

Spring Cloud LoadBalancer 生命周期

LoadBalancerLifecycle bean 提供名为 onStart(Request<RC> request) 、 onStartRequest(Request<RC> request, Response<T> lbResponse) 和 onComplete(CompletionContext<RES, T, RC> completionContext) 的回调方法,您应该实现这些方法来指定之前应该执行哪些操作以及负载均衡之后。

onStart(Request<RC> request) 将 Request 对象作为参数。它包含用于选择适当实例的数据,包括下游客户端请求和提示。 onStartRequest 还采用 Request 对象以及 Response<T> 对象作为参数。另一方面, CompletionContext 对象被提供给 onComplete(CompletionContext<RES, T, RC> completionContext) 方法。它包含 LoadBalancer Response ,包括选定的服务实例、针对该服务实例执行的请求的 Status 以及(如果可用)返回到下游客户端的响应,以及(如果发生异常)对应的 Throwable 。

Spring Cloud LoadBalancer 统计

我们提供了一个名为 MicrometerStatsLoadBalancerLifecycle 的 LoadBalancerLifecycle bean,它使用 Micrometer 提供负载平衡调用的统计信息。

为了将此 bean 添加到您的应用程序上下文中,请将 spring.cloud.loadbalancer.stats.micrometer.enabled 的值设置为 true 并让 MeterRegistry 可用(例如,通过添加 Spring将执行器启动到您的项目)。

MicrometerStatsLoadBalancerLifecycle 在 MeterRegistry 中注册以下计量表:

loadbalancer.requests.active :一个仪表,允许您监视任何服务实例当前活动请求的数量(通过标签提供的服务实例数据);

loadbalancer.requests.success :一个计时器,用于测量已结束将响应传递给底层客户端的任何负载平衡请求的执行时间;

loadbalancer.requests.failed :一个计时器,用于测量任何以异常结束的负载均衡请求的执行时间;

loadbalancer.requests.discard :一个计数器,用于测量丢弃的负载平衡请求的数量,即 LoadBalancer 尚未检索到运行请求的服务实例的请求。

配置单独的 LoadBalancerClient

可以使用不同的前缀 spring.cloud.loadbalancer.clients.<clientId>. 单独配置各个负载均衡器客户端,其中 clientId 是负载均衡器的名称。默认配置值可以在 spring.cloud.loadbalancer. 命名空间中设置,并将优先与客户端特定值合并

application.yml

spring:cloud:loadbalancer:health-check:initial-delay: 1sclients:myclient:health-check:interval: 30s

上面的示例将生成一个与 initial-delay=1s 和 interval=30s 合并的运行状况检查 @ConfigurationProperties 对象。

除以下全局属性外,每个客户端配置属性适用于大多数属性:

spring.cloud.loadbalancer.enabled - 全局启用或禁用负载平衡

spring.cloud.loadbalancer.retry.enabled - 全局启用或禁用负载平衡重试。如果全局启用它,您仍然可以使用 client 前缀属性禁用特定客户端的重试,但反之则不然

spring.cloud.loadbalancer.cache.enabled - 全局启用或禁用 LoadBalancer 缓存。如果全局启用它,您仍然可以通过创建在 ServiceInstanceListSupplier 委托层次结构中不包含 CachingServiceInstanceListSupplier 的自定义配置来禁用特定客户端的缓存,但反之则不然。

spring.cloud.loadbalancer.stats.micrometer.enabled - 全局启用或禁用 LoadBalancer Micrometer 指标

[[-aot-and-native-image-support]] == AOT 和本机映像支持

从 4.0.0 开始,Spring Cloud LoadBalancer 支持 Spring AOT 转换和原生镜像。但是,要使用此功能,您需要显式定义您的 LoadBalancerClient 服务 ID。您可以通过使用 @LoadBalancerClient 注释的 value 或 name 属性或作为 spring.cloud.loadbalancer.eager-load.clients 属性的值来执行此操作。

LoadBalancer上下文的即时加载

Spring Cloud LoadBalancer 为每个服务 id 创建一个单独的 Spring 子上下文。默认情况下,每当对服务 ID 的第一个请求进行负载平衡时,这些上下文都会被延迟初始化。

您可以选择立即加载这些上下文。为此,请使用 spring.cloud.loadbalancer.eager-load.clients 属性指定要执行预加载的服务 ID,例如:

spring.cloud-loadbalancer.eager-load.clients[0]=my-first-client
spring.cloud-loadbalancer.eager-load.clients[1]=my-second-client

负载均衡算法之间的切换

默认情况下使用的 ReactiveLoadBalancer 实现是 RoundRobinLoadBalancer 。要切换到不同的实现(对于选定的服务或所有服务),您可以使用自定义 LoadBalancer 配置机制。


例如,可以通过 @LoadBalancerClient 注释传递以下配置以切换为使用 RandomLoadBalancer :

public class CustomLoadBalancerConfiguration {@BeanReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),name);}
}

作为 @LoadBalancerClient 或 @LoadBalancerClients 配置参数传递的类不应使用 @Configuration 进行注释,或者位于组件扫描范围之外。

Spring Cloud LoadBalancer 缓存

除了每次必须选择实例时通过 DiscoveryClient 检索实例的基本 ServiceInstanceListSupplier 实现之外,我们还提供了两种缓存实现。

即为:可以先将实例缓存起来,每次直接从缓存中选取实例

如果类路径中有 com.github.ben-manes.caffeine:caffeine ,则将使用基于 Caffeine的实现。有关如何配置它的信息,请参阅 LoadBalancerCacheConfiguration 部分。

如果您使用 Caffeine,还可以通过在 spring.cloud.loadbalancer.cache.caffeine.spec 属性中传递您自己的 Caffeine 规范来覆盖 LoadBalancer 的默认 Caffeine 缓存设置。

警告:传递您自己的 Caffeine 规范将覆盖任何其他 LoadBalancerCache 设置,包括常规 LoadBalancer 缓存配置字段,例如 ttl 和 capacity 。

默认 LoadBalancer 缓存实现

如果类路径中没有 Caffeine,则将使用 spring-cloud-starter-loadbalancer 自动附带的 DefaultLoadBalancerCache 。有关如何配置它的信息,请参阅 LoadBalancerCacheConfiguration 部分。

使用 Caffeine 而不是默认缓存,请将 com.github.ben-manes.caffeine:caffeine 依赖项添加到类路径。

负载均衡器缓存配置

您可以设置自己的 ttl 值(写入后的时间,在此之后条目应过期),表示为 Duration ,通过传递符合 Spring 的 String 将 String 引导到 Duration 转换器语法。作为 spring.cloud.loadbalancer.cache.ttl 属性的值。您还可以通过设置 spring.cloud.loadbalancer.cache.capacity 属性的值来设置自己的LoadBalancer缓存初始容量。

默认设置包括将 ttl 设置为 35 秒,默认 initialCapacity 为 256 。

您还可以通过将 spring.cloud.loadbalancer.cache.enabled 的值设置为 false 来完全禁用 loadBalancer 缓存。

注意:

        尽管基本的非缓存实现对于原型设计和测试很有用,但它的效率比缓存版本低得多,因此我们建议在生产中始终使用缓存版本。如果 DiscoveryClient 实现已完成缓存,例如 EurekaDiscoveryClient ,则应禁用负载均衡器缓存以防止双重缓存。

加权负载平衡

为了启用加权负载平衡,我们提供 WeightedServiceInstanceListSupplier 。我们使用 WeightFunction 来计算每个实例的权重。默认情况下,我们尝试从元数据映射中读取并解析权重(键为 weight )。

如果元数据映射中没有指定权重,我们默认该实例的权重为1。

可以通过将 spring.cloud.loadbalancer.configurations 的值设置为 weighted 或提供您自己的 ServiceInstanceListSupplier bean 来配置它,例如:

public class CustomLoadBalancerConfiguration {@Beanpublic ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {return ServiceInstanceListSupplier.builder().withDiscoveryClient().withWeighted().withCaching().build(context);}
}

您还可以通过提供 WeightFunction 来自定义权重计算逻辑。

您可以使用此示例配置使所有实例具有随机权重:

public class CustomLoadBalancerConfiguration {@Beanpublic ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {return ServiceInstanceListSupplier.builder().withDiscoveryClient().withWeighted(instance -> ThreadLocalRandom.current().nextInt(1, 101)).withCaching().build(context);}
}

基于区域的负载平衡

为了启用基于区域的负载平衡,我们提供 ZonePreferenceServiceInstanceListSupplier 。我们使用 DiscoveryClient 特定的 zone 配置(例如 eureka.instance.metadata-map.zone )来选择客户端尝试过滤可用服务实例的区域。

您还可以通过设置 spring.cloud.loadbalancer.zone 属性的值来覆盖 DiscoveryClient 特定区域设置。

目前,仅使用 Eureka Discovery 客户端来设置 LoadBalancer 区域。对于其他发现客户端,请设置 spring.cloud.loadbalancer.zone 属性。更多仪器即将推出。

为了确定检索到的 ServiceInstance 的区域,我们检查其元数据映射中 "zone" 键下的值。

ZonePreferenceServiceInstanceListSupplier 过滤检索到的实例并仅返回同一区域内的实例。如果区域是 null 或者同一区域内没有实例,则返回所有检索到的实例。

为了使用基于区域的负载平衡方法,您必须在自定义配置中实例化 ZonePreferenceServiceInstanceListSupplier bean。

我们使用委托来处理 ServiceInstanceListSupplier bean。我们建议使用 DiscoveryClientServiceInstanceListSupplier 委托,用 CachingServiceInstanceListSupplier 包装它以利用 LoadBalancer 缓存机制,然后将生成的 bean 传递到 ZonePreferenceServiceInstanceListSupplier 的构造函数中。

public class CustomLoadBalancerConfiguration {@Beanpublic ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {return ServiceInstanceListSupplier.builder().withDiscoveryClient().withCaching().withZonePreference().build(context);}
}

LoadBalancer 的实例健康检查

可以为 LoadBalancer 启用计划的运行状况检查。 HealthCheckServiceInstanceListSupplier 就是为此提供的。它定期验证委托 ServiceInstanceListSupplier 提供的实例是否仍然存在,并且只返回健康的实例,除非没有 - 然后它返回所有检索到的实例。

这种机制在使用 SimpleDiscoveryClient 时特别有用。对于由实际服务注册表支持的客户端,没有必要使用它,因为我们在查询外部 ServiceDiscovery 后已经获得了健康的实例。

如果使用任何服务发现支持的供应商,通常不需要添加此运行状况检查机制,因为我们直接从服务注册表检索实例的运行状况。

LoadBalancer 的相同实例首选项

您可以设置 LoadBalancer,使其优先选择之前选择的实例(如果该实例可用)。

为此,您需要使用 SameInstancePreferenceServiceInstanceListSupplier 。您可以通过将 spring.cloud.loadbalancer.configurations 的值设置为 same-instance-preference 或提供您自己的 ServiceInstanceListSupplier bean 来配置它 - 例如:

public class CustomLoadBalancerConfiguration {@Beanpublic ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {return ServiceInstanceListSupplier.builder().withDiscoveryClient().withSameInstancePreference().build(context);}}

LoadBalancer 基于请求的粘性会话

您可以设置 LoadBalancer,使其优先使用请求 cookie 中提供的 instanceId 实例。如果请求通过 ClientRequestContext 或 ServerHttpRequestContext 传递到 LoadBalancer(SC LoadBalancer 交换过滤器函数和过滤器使用这些请求),我们目前支持此操作。


为此,您需要使用 RequestBasedStickySessionServiceInstanceListSupplier 。您可以通过将 spring.cloud.loadbalancer.configurations 的值设置为 request-based-sticky-session 或提供您自己的 ServiceInstanceListSupplier bean 来配置它 - 例如:

public class CustomLoadBalancerConfiguration {@Beanpublic ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {return ServiceInstanceListSupplier.builder().withDiscoveryClient().withRequestBasedStickySession().build(context);}}

对于该功能,在转发请求之前更新选定的服务实例(如果原始请求 cookie 中的服务实例不可用,则该实例可能与原始请求 cookie 中的服务实例不同)很有用。为此,请将 spring.cloud.loadbalancer.sticky-session.add-service-instance-cookie 的值设置为 true 。

基于提示的负载平衡

我们还提供了 HintBasedServiceInstanceListSupplier ,它是基于提示的实例选择的 ServiceInstanceListSupplier 实现。

HintBasedServiceInstanceListSupplier 检查提示请求标头(默认标头名称为 X-SC-LB-Hint ,但您可以通过更改 spring.cloud.loadbalancer.hint-header-name 属性的值来修改它),并且,如果找到提示请求标头,则使用标头中传递的提示值来过滤服务实例。

如果未添加提示标头, HintBasedServiceInstanceListSupplier 将使用属性中的提示值来过滤服务实例。

如果未通过标头或属性设置提示,则返回委托提供的所有服务实例。

过滤时, HintBasedServiceInstanceListSupplier 查找在其 metadataMap 中的 hint 键下设置了匹配值的服务实例。如果没有找到匹配的实例,则返回委托提供的所有实例。

您可以使用以下示例配置来进行设置:

public class CustomLoadBalancerConfiguration {@Beanpublic ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {return ServiceInstanceListSupplier.builder().withDiscoveryClient().withCaching().withHints().build(context);}
}

转换负载平衡的 HTTP 请求

您可以使用所选的 ServiceInstance 来转换负载平衡的HTTP请求。

对于 RestTemplate 和 RestClient ,您需要按如下方式实现和定义 LoadBalancerRequestTransformer :

@Bean
public LoadBalancerRequestTransformer transformer() {return new LoadBalancerRequestTransformer() {@Overridepublic HttpRequest transformRequest(HttpRequest request, ServiceInstance instance) {return new HttpRequestWrapper(request) {@Overridepublic HttpHeaders getHeaders() {HttpHeaders headers = new HttpHeaders();headers.putAll(super.getHeaders());headers.add("X-InstanceId", instance.getInstanceId());return headers;}};}};
}

对于 WebClient ,您需要实现并定义 LoadBalancerClientRequestTransformer ,如下所示:

@Bean
public LoadBalancerClientRequestTransformer transformer() {return new LoadBalancerClientRequestTransformer() {@Overridepublic ClientRequest transformRequest(ClientRequest request, ServiceInstance instance) {return ClientRequest.from(request).header("X-InstanceId", instance.getInstanceId()).build();}};
}

如果定义了多个转换器,它们将按照定义 Bean 的顺序应用。或者,您可以使用 LoadBalancerRequestTransformer.DEFAULT_ORDER 或 LoadBalancerClientRequestTransformer.DEFAULT_ORDER 指定顺序。

Spring Cloud LoadBalancer 子集

SubsetServiceInstanceListSupplier 实现确定性子集算法,以在 ServiceInstanceListSupplier 委托层次结构中选择有限数量的实例。

您可以通过将 spring.cloud.loadbalancer.configurations 的值设置为 subset 或提供您自己的 ServiceInstanceListSupplier bean 来配置它 - 例如:

public class CustomLoadBalancerConfiguration {@Beanpublic ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(ConfigurableApplicationContext context) {return ServiceInstanceListSupplier.builder().withDiscoveryClient().withSubset().withCaching().build(context);}}

默认情况下,每个服务实例都会分配一个唯一的 instanceId ,不同的 instanceId 值通常会选择不同的子集。正常情况下,无需关注。但是,如果需要让多个实例选择相同的子集,则可以使用 spring.cloud.loadbalancer.subset.instance-id (支持占位符)进行设置。

默认情况下,子集的大小设置为 100。您也可以使用 spring.cloud.loadbalancer.subset.size 进行设置。

这篇关于Spring Cloud LoadBalancer 4.1.2的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/978835

相关文章

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代

Java使用SLF4J记录不同级别日志的示例详解

《Java使用SLF4J记录不同级别日志的示例详解》SLF4J是一个简单的日志门面,它允许在运行时选择不同的日志实现,这篇文章主要为大家详细介绍了如何使用SLF4J记录不同级别日志,感兴趣的可以了解下... 目录一、SLF4J简介二、添加依赖三、配置Logback四、记录不同级别的日志五、总结一、SLF4J

将Java项目提交到云服务器的流程步骤

《将Java项目提交到云服务器的流程步骤》所谓将项目提交到云服务器即将你的项目打成一个jar包然后提交到云服务器即可,因此我们需要准备服务器环境为:Linux+JDK+MariDB(MySQL)+Gi... 目录1. 安装 jdk1.1 查看 jdk 版本1.2 下载 jdk2. 安装 mariadb(my

SpringBoot中配置Redis连接池的完整指南

《SpringBoot中配置Redis连接池的完整指南》这篇文章主要为大家详细介绍了SpringBoot中配置Redis连接池的完整指南,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以... 目录一、添加依赖二、配置 Redis 连接池三、测试 Redis 操作四、完整示例代码(一)pom.

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

Java Optional的使用技巧与最佳实践

《JavaOptional的使用技巧与最佳实践》在Java中,Optional是用于优雅处理null的容器类,其核心目标是显式提醒开发者处理空值场景,避免NullPointerExce... 目录一、Optional 的核心用途二、使用技巧与最佳实践三、常见误区与反模式四、替代方案与扩展五、总结在 Java

基于Java实现回调监听工具类

《基于Java实现回调监听工具类》这篇文章主要为大家详细介绍了如何基于Java实现一个回调监听工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录监听接口类 Listenable实际用法打印结果首先,会用到 函数式接口 Consumer, 通过这个可以解耦回调方法,下面先写一个

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析