Spring Cloud LoadBalancer
Spring Cloud 提供自己的客户端负载均衡器抽象和实现。对于负载均衡机制,已添加 ReactiveLoadBalancer
接口,并为它提供了 Round-Robin-based 和 Random 实现。为了从响应式 ServiceInstanceListSupplier`中获取要选择的实例,我们已使用它。当前,我们支持 `ServiceInstanceListSupplier
的基于服务发现的实现,它使用类路径中可用的 Discovery Client 从服务发现中检索可用实例。
可以通过将 |
Eager loading of LoadBalancer contexts
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
Switching between the load-balancing algorithms
默认使用的 ReactiveLoadBalancer
实现是 RoundRobinLoadBalancer
。要在选定的服务或所有服务中切换到不同的实现,可以使用 custom LoadBalancer configurations mechanism。
例如,可以通过 @LoadBalancerClient
注释传递以下配置,以切换到使用 RandomLoadBalancer
:
public class CustomLoadBalancerConfiguration {
@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(loadBalancerClientFactory
.getLazyProvider(name, ServiceInstanceListSupplier.class),
name);
}
}
你作为 |
Spring Cloud LoadBalancer integrations
为了便于使用 Spring Cloud LoadBalancer,我们提供了 ReactorLoadBalancerExchangeFilterFunction
(可与 WebClient
搭配使用)和 BlockingLoadBalancerClient
(可与 RestTemplate
和 RestClient
搭配使用)。你可以在以下部分中看到更多信息和使用示例:
Spring Cloud LoadBalancer Caching
除了每次必须选择一个实例时都会通过 DiscoveryClient
检索实例的基本 ServiceInstanceListSupplier
实现之外,我们还提供了两种缓存实现。
如果类路径中存在 com.github.ben-manes.caffeine:caffeine
,则将使用基于 Caffeine 的实现。有关如何配置它的信息,请参见 LoadBalancerCacheConfiguration部分。
如果您使用的是 Caffeine,还可以通过在 `spring.cloud.loadbalancer.cache.caffeine.spec`属性中传递自己的 Caffeine Specification来覆盖负载均衡器的默认 Caffeine 缓存设置。
警告:传递你自己的 Caffeine 规范将覆盖所有其他 LoadBalancerCache 设置,包括 ttl
和 capacity
等 General LoadBalancer Cache Configuration 字段。
Default LoadBalancer Cache Implementation
如果类路径中没有 Caffeine,则将使用自动与 spring-cloud-starter-loadbalancer
一起提供的 DefaultLoadBalancerCache
。有关如何配置它的信息,请参见 LoadBalancerCacheConfiguration 部分。
要使用 Caffeine 而不是默认缓存,请将 |
LoadBalancer Cache Configuration
你可以通过将 Spring Boot String
至 Duration
转换器语法 compliant with the link:https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-conversion-duration[的 String
作为 spring.cloud.loadbalancer.cache.ttl
属性的值传递,设置自己的 ttl
值(写入后应使条目过期的时长),表示为 Duration
。你还可以通过设置 spring.cloud.loadbalancer.cache.capacity
属性的值来设置自己的 LoadBalancer 缓存初始容量。
默认设置包括将 ttl
设为 35 秒,而默认 initialCapacity
为 256
。
你也可以通过将 spring.cloud.loadbalancer.cache.enabled
的值设为 false
来彻底禁用负载均衡器缓存。
尽管基本的不带缓存的实现对于原型设计和测试非常有用,但它的效率远低于缓存版本,因此我们建议在生产环境中始终使用缓存版本。如果 DiscoveryClient
实现(例如 EurekaDiscoveryClient
)已经完成了缓存,则应禁用负载均衡器缓存,以防止双重缓存。
当你创建自己的配置时,如果你使用了 |
Weighted Load-Balancing
为了启用加权负载均衡,我们提供了 WeightedServiceInstanceListSupplier
。我们使用 WeightFunction
来计算每个实例的权重。默认情况下,我们尝试从元数据映射(密钥为 weight
)中读取和解析权重。
如果元数据映射中未指定权重,则默认此实例的权重为 1。
你可以通过将 spring.cloud.loadbalancer.configurations
的值设为 weighted
或提供你自己的 ServiceInstanceListSupplier
Bean 来配置它,例如:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withWeighted()
.withCaching()
.build(context);
}
}
你还可以通过提供 |
你可以使用此样本配置让所有实例具有随机权重:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withWeighted(instance -> ThreadLocalRandom.current().nextInt(1, 101))
.withCaching()
.build(context);
}
}
Zone-Based Load-Balancing
为了启用基于区域的负载均衡,我们提供了 ZonePreferenceServiceInstanceListSupplier
。我们使用`DiscoveryClient` 特定的 zone
配置(例如,eureka.instance.metadata-map.zone
)来选择客户端为其尝试筛选可用服务实例的区域。
你还可以通过设置 |
目前,只有 Eureka Discovery Client 会被配置为设置 LoadBalancer 区域。对于其他发现客户端,设置 spring.cloud.loadbalancer.zone
属性。其他设备将很快推出。
要确定一个已检索的 |
ZonePreferenceServiceInstanceListSupplier
筛选检索的实例,并仅返回同一区域中的实例。如果 zone
为 null
或者同一区域中没有实例,它将返回所有检索的实例。
为了使用基于区域的负载均衡方法,你必须在 custom configuration 中实例化 ZonePreferenceServiceInstanceListSupplier
Bean。
我们使用委托与 ServiceInstanceListSupplier
Bean 一起工作。我们建议使用 DiscoveryClientServiceInstanceListSupplier
委托,使用 CachingServiceInstanceListSupplier
包装它以利用 LoadBalancer caching mechanism,然后在 ZonePreferenceServiceInstanceListSupplier
的构造函数中传递生成的 Bean。
你可以使用此样本配置对其进行设置:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withCaching()
.withZonePreference()
.build(context);
}
}
Instance Health-Check for LoadBalancer
可以启用 LoadBalancer 的计划性健康检查。为此,提供了 HealthCheckServiceInstanceListSupplier
。它会定期验证由委托 ServiceInstanceListSupplier
提供的实例是否仍然可用,并仅返回可用的实例,除非不存在这些实例 - 那么它将返回所有检索的实例。
使用 |
此供应商还建议用于每项服务只有一小部分实例的设置,以避免在失败的实例上重试调用。 |
如果使用任何由服务发现支持的供应商,通常不需要添加此运行状况检查机制,因为我们直接从服务注册表中检索实例的运行状况状态。
|
HealthCheckServiceInstanceListSupplier
使用加有 spring.cloud.loadbalancer.health-check
前缀的属性。您可以为计划程序设置 initialDelay
和 interval
。您可以通过设置 spring.cloud.loadbalancer.health-check.path.default
属性的值来为健康检查 URL 设置默认路径。您还可以通过设置 spring.cloud.loadbalancer.health-check.path.[SERVICE_ID]
属性的值来为给定的服务设置特定值,用您的服务的正确 ID 替换 [SERVICE_ID]
。如果未指定 [SERVICE_ID]
,则默认使用 /actuator/health
。如果将 [SERVICE_ID]
设置为 null
或为空值,则不会执行健康检查。您还可以通过设置 spring.cloud.loadbalancer.health-check.port
的值来为健康检查请求设置自定义端口。如果没有设置,则端口是指所请求的服务可在服务实例中获得的端口。
如果您使用默认路径 ( |
默认情况下, |
为了使用运行状况检查时间表方法,你必须在 custom configuration 中实例化 HealthCheckServiceInstanceListSupplier
Bean。
我们使用委托来处理 ServiceInstanceListSupplier
Bean。我们建议在 HealthCheckServiceInstanceListSupplier
的构造函数中传入一个 DiscoveryClientServiceInstanceListSupplier
委托。
你可以使用此样本配置对其进行设置:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withHealthChecks()
.build(context);
}
}
对于非反应堆栈,请使用 |
HealthCheckServiceInstanceListSupplier
具有基于 Reactor Flux replay()
的自己的缓存机制。因此,如果使用它,您可能需要跳过使用 `CachingServiceInstanceListSupplier`包装此供应商。
创建您自己的配置时, |
Same instance preference for LoadBalancer
你可以以这样一种方式设置 LoadBalancer,即如果可用,它会倾向于选择之前已选择的实例。
为此,你需要使用 SameInstancePreferenceServiceInstanceListSupplier
。你可以通过将 spring.cloud.loadbalancer.configurations
的值设为 same-instance-preference
或提供你自己的 ServiceInstanceListSupplier
Bean(例如)来配置它:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withSameInstancePreference()
.build(context);
}
}
这也是 Zookeeper |
Request-based Sticky Session for LoadBalancer
你可以以这样一种方式设置 LoadBalancer,即它会根据请求 Cookie 中提供的 instanceId
倾向于选择实例。如果请求通过 ClientRequestContext 或 ServerHttpRequestContext 传递给 LoadBalancer,我们目前支持这一点,这些 Context 由 SC LoadBalancer 交换过滤器函数和过滤器使用。
为此,你需要使用 RequestBasedStickySessionServiceInstanceListSupplier
。你可以通过将 spring.cloud.loadbalancer.configurations
的值设为 request-based-sticky-session
或提供你自己的 ServiceInstanceListSupplier
Bean(例如)来配置它:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withRequestBasedStickySession()
.build(context);
}
}
对于该功能,将选定的服务实例(如果原始请求 Cookie 中的实例不可用,则可以与原始请求 Cookie 中的实例不同)在发送请求前进行更新非常有用。为此,将 spring.cloud.loadbalancer.sticky-session.add-service-instance-cookie
的值设为 true
。
默认情况下,Cookie 的名称为 sc-lb-instance-id
。您可以通过更改 spring.cloud.loadbalancer.instance-id-cookie-name
属性的值来修改它。
当前,WebClient 支持此功能实现负载均衡。 |
Spring Cloud LoadBalancer Hints
Spring Cloud LoadBalancer 让您可以设置在 Request
对象内传递到负载均衡器的 String
提示,此后这将在可以处理它们的 ReactiveLoadBalancer
实现中使用。
您可以通过设置 spring.cloud.loadbalancer.hint.default
属性的值来为所有服务设置一个默认提示。您还可通过设置 spring.cloud.loadbalancer.hint.[SERVICE_ID]
属性的值来为给定的服务设置特定值,用您的服务的正确 ID 替换 [SERVICE_ID]
。如果用户未设置提示,则使用 default
。
Hint-Based Load-Balancing
我们还提供了一个 HintBasedServiceInstanceListSupplier
,它是一个用于基于提示的实例选择的 ServiceInstanceListSupplier
实现。
HintBasedServiceInstanceListSupplier
会检查提示请求头(默认头名称为 X-SC-LB-Hint
,但您可以通过更改 spring.cloud.loadbalancer.hint-header-name
属性的值来修改它),并且如果它找到提示请求头,则会使用头中传递的提示值来过滤服务实例。
如果没有添加提示标头,则 HintBasedServiceInstanceListSupplier
使用 hint values from properties 过滤服务实例。
如果未设置提示(无论通过头还是属性),都将返回委托提供的全部服务实例。
在过滤过程中,HintBasedServiceInstanceListSupplier
会寻找在其 metadataMap
中的 hint
键下具有匹配值设置的服务实例。如果没有找到匹配的实例,则将返回委托提供的全部实例。
您可以使用以下示例配置来设置它:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withCaching()
.withHints()
.build(context);
}
}
Transform the load-balanced HTTP request
您可以使用选定的 ServiceInstance
来转换负载均衡的 HTTP 请求。
对于 RestTemplate
和 RestClient
,您需要按如下方式实现并定义 LoadBalancerRequestTransformer
:
@Bean
public LoadBalancerRequestTransformer transformer() {
return new LoadBalancerRequestTransformer() {
@Override
public HttpRequest transformRequest(HttpRequest request, ServiceInstance instance) {
return new HttpRequestWrapper(request) {
@Override
public 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() {
@Override
public 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 Subset
SubsetServiceInstanceListSupplier
实施了一个 deterministic subsetting algorithm 在 ServiceInstanceListSupplier
委托层次结构中选择数量有限的实例。
您可以通过将 spring.cloud.loadbalancer.configurations
的值设置为 subset
或提供您自己的 ServiceInstanceListSupplier
bean 来配置它,例如:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withSubset()
.withCaching()
.build(context);
}
}
默认情况下,每个服务实例都分配一个唯一的 |
默认情况下,子集大小设置为 100。您还可以使用 |
Spring Cloud LoadBalancer Starter
我们还提供了一个 starter,让您轻松在 Spring Boot 应用程序中添加 Spring Cloud LoadBalancer。要使用它,只需在构建文件中将 org.springframework.cloud:spring-cloud-starter-loadbalancer
添加到您的 Spring Cloud 依赖项中。
Spring Cloud LoadBalancer starter 包括 Spring Boot Caching和 Evictor。 |
Passing Your Own Spring Cloud LoadBalancer Configuration
您还可以使用 @LoadBalancerClient
注释来传递您自己的负载均衡器客户端配置,如下所述传递负载均衡器客户端的名称和配置类:
@Configuration
@LoadBalancerClient(value = "stores", configuration = CustomLoadBalancerConfiguration.class)
public class MyConfiguration {
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}
}
为了让您更轻松地处理您自己的 LoadBalancer 配置,我们已向 |
您还可以使用我们的其他预定义配置代替默认配置,通过将 |
您可以使用此功能来实例化您自己编写或我们提供作为替代方案(例如 ZonePreferenceServiceInstanceListSupplier
)的 ServiceInstanceListSupplier
或 ReactorLoadBalancer
的不同实现,以覆盖默认设置。
你可以看到自定义配置 here 的示例。
注释 |
您还可以通过 @LoadBalancerClients
注释传递多个配置(用于多个负载均衡器客户端),如下面的示例所示:
@Configuration
@LoadBalancerClients({@LoadBalancerClient(value = "stores", configuration = StoresLoadBalancerClientConfiguration.class), @LoadBalancerClient(value = "customers", configuration = CustomersLoadBalancerClientConfiguration.class)})
public class MyConfiguration {
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}
}
你作为 |
创建您自己的配置时,如果您使用 |
Spring Cloud LoadBalancer Lifecycle
可能使用 Custom LoadBalancer configuration 注册的一类 Bean 是 LoadBalancerLifecycle
。
LoadBalancerLifecycle
Bean 提供名为 onStart(Request<RC> request)
、onStartRequest(Request<RC> request, Response<T> lbResponse)
和 onComplete(CompletionContext<RES, T, RC> completionContext)
的回调方法,您应实现这些方法来指定在负载均衡前后应执行哪些操作。
onStart(Request<RC> request)
接收 Request
对象作为参数。它包含用于选择适当实例的数据,包括下游客户端请求和 hint。onStartRequest
也接收 Request
对象,此外,还将 Response<T>
对象作为参数。另一方面,向 onComplete(CompletionContext<RES, T, RC> completionContext)
方法提供了 CompletionContext
对象。它包含负载均衡器 Response
,包括所选的服务实例、对该服务实例执行的请求的 Status
以及(如果可用)返回给下游客户端的响应,以及(如果发生异常)相应的 Throwable
。
supports(Class requestContextClass, Class responseClass,Class serverTypeClass)
方法可用于确定有问题的处理器是否会处理所提供类型对象。如果没有被用户覆盖,它会返回 true
。
在前面的方法调用中, |
Spring Cloud LoadBalancer Statistics
我们提供了一个名为 MicrometerStatsLoadBalancerLifecycle
的 LoadBalancerLifecycle
Bean,它使用 Micrometer 为负载均衡的调用提供统计数据。
要将此 bean 添加到应用程序上下文,请将 spring.cloud.loadbalancer.stats.micrometer.enabled
的值设置为 true
,并提供一个 MeterRegistry
(例如,通过将 Spring Boot Actuator 添加到您的项目)。
MicrometerStatsLoadBalancerLifecycle
在 MeterRegistry
中注册以下指标:
-
loadbalancer.requests.active
:一个监测器,可用来监测任何服务实例当前活动的请求数量(服务实例数据通过标签获取); -
loadbalancer.requests.success
:计时器,用于测量已结束,并将响应传递到基础客户端的任何负载均衡请求的执行时间; -
loadbalancer.requests.failed
:计时器,用于测量因异常而结束的任何负载均衡请求的执行时间; -
loadbalancer.requests.discard
:计数器,用于测量已放弃的负载均衡请求的数量,即 LoadBalancer 未检索到在请求上运行服务的实例的请求。
每当存在时,都会通过标签向指标添加有关服务实例、请求数据和响应数据更多信息相关的信息。
对于某些实现,例如 |
当至少为给定测量仪添加一条记录时,会在注册表中注册测量仪。 |
您可以通过 adding |
Configuring Individual LoadBalancerClients
可以通过不同的前缀 spring.cloud.loadbalancer.clients.<clientId>.
单独配置个别 Loadbalancer 客户端,其中 clientId
是负载均衡器的名称。可以在 spring.cloud.loadbalancer.
命名空间中设置默认配置值,并将其与特定于客户端的值合并,其中客户端值优先。
spring: cloud: loadbalancer: health-check: initial-delay: 1s clients: myclient: health-check: interval: 30s
以上示例将得到一个合并的健康检查 @ConfigurationProperties
对象,其中 initial-delay=1s
,interval=30s
。
每个客户端的配置属性适用于大部分属性,以下全局属性除外:
-
spring.cloud.loadbalancer.enabled
- 允许或禁止负载均衡 -
spring.cloud.loadbalancer.retry.enabled
- 允许或禁止负载均衡重试。如果启用了全局重试,仍可以使用带client
前缀的属性为特定客户端禁用重试,但不能反过来 -
spring.cloud.loadbalancer.cache.enabled
- 全局启用或禁用 LoadBalancer 缓存。如果您在全局范围内启用它,您仍然可以通过在ServiceInstanceListSupplier
委托层级中不包含CachingServiceInstanceListSupplier
的 custom configuration 来为特定客户端禁用缓存,但不能反过来做。 -
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
属性的值来执行此操作。