3. Spring Cloud 负载均衡器
Spring Cloud 提供了自己的客户端负载均衡器抽象和实现。对于负载均衡
机制、接口以及基于 Round-Robin 和 Random 的实现
已经为此提供了。为了从 中选择实例,使用了 reactive 。目前,我们支持基于 service-discovery 的实现,它使用 Classpath 中可用的 Discovery Client 从 Service Discovery 中检索可用实例。ReactiveLoadBalancer
ServiceInstanceListSupplier
ServiceInstanceListSupplier
可以通过将 的值设置为 来禁用 Spring Cloud LoadBalancer 。spring.cloud.loadbalancer.enabled false |
3.1. 在负载均衡算法之间切换
默认使用的实现是 。要切换到其他实现,无论是针对所选服务还是所有服务,您可以使用自定义 LoadBalancer 配置机制。ReactiveLoadBalancer
RoundRobinLoadBalancer
例如,可以通过 annotation 传递以下配置以切换到使用 :@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);
}
}
您传递的类或配置参数不应使用 Comments 或超出组件扫描范围。@LoadBalancerClient @LoadBalancerClients @Configuration |
3.2. Spring Cloud LoadBalancer 集成
为了便于使用 Spring Cloud LoadBalancer,我们提供了可与 .
您可以在以下部分中查看详细信息和使用示例:ReactorLoadBalancerExchangeFilterFunction
WebClient
BlockingLoadBalancerClient
RestTemplate
3.3. Spring Cloud LoadBalancer 缓存
除了每次必须选择实例时检索实例的基本实现外,我们还提供了两种缓存实现。ServiceInstanceListSupplier
DiscoveryClient
3.3.1. Caffeine 支持的 LoadBalancer 缓存实现
如果您在 Classpath 中有,则将使用基于 Caffeine 的实现。
有关如何配置它的信息,请参阅 LoadBalancerCacheConfiguration 部分。com.github.ben-manes.caffeine:caffeine
如果您使用的是 Caffeine,您还可以通过在属性中传递您自己的 Caffeine Specification 来覆盖 LoadBalancer 的默认 Caffeine Cache 设置。spring.cloud.loadbalancer.cache.caffeine.spec
警告:传递您自己的 Caffeine 规范将覆盖任何其他 LoadBalancerCache 设置,包括 General LoadBalancer Cache Configuration 字段,例如 和 。ttl
capacity
3.3.2. 默认 LoadBalancer 缓存实现
如果 Classpath 中没有 Caffeine,则将使用 ,它自动随 .
有关如何配置它的信息,请参阅 LoadBalancerCacheConfiguration 部分。DefaultLoadBalancerCache
spring-cloud-starter-loadbalancer
要使用 Caffeine 而不是默认缓存,请将依赖项添加到 Classpath。com.github.ben-manes.caffeine:caffeine |
3.3.3. LoadBalancer 缓存配置
你可以设置自己的值(写入后的时间,在此时间之后条目应过期),表示为 ,通过传递符合 Spring Boot String
to Duration
转换器语法。
作为属性的值。
您还可以通过设置属性的值来设置自己的 LoadBalancer 缓存初始容量。ttl
Duration
String
spring.cloud.loadbalancer.cache.ttl
spring.cloud.loadbalancer.cache.capacity
默认设置包括设置为 35 秒,默认值为 。ttl
initialCapacity
256
您还可以通过将 的值设置为 .spring.cloud.loadbalancer.cache.enabled
false
尽管基本的非缓存实现对于原型设计和测试很有用,但它的效率远低于缓存版本,因此我们建议在生产中始终使用缓存版本。如果 implementation 已经完成了缓存,例如,应禁用负载均衡器缓存以防止双重缓存。DiscoveryClient EurekaDiscoveryClient |
在创建自己的配置时,如果使用,请确保将其放在层次结构中,直接位于通过网络检索实例的供应商之后,例如,在任何其他筛选供应商之前。CachingServiceInstanceListSupplier DiscoveryClientServiceInstanceListSupplier |
3.4. 基于区域的负载均衡
为了实现基于区域的负载均衡,我们提供了 .
我们使用特定于 的配置(例如 )来选择客户端尝试筛选可用服务实例的区域。ZonePreferenceServiceInstanceListSupplier
DiscoveryClient
zone
eureka.instance.metadata-map.zone
您还可以通过设置 property 的值来覆盖 -specific zone 设置。DiscoveryClient spring.cloud.loadbalancer.zone |
目前,只有 Eureka Discovery Client 被检测来设置 LoadBalancer 区域。对于其他发现客户端,请设置该属性。更多仪器即将推出。spring.cloud.loadbalancer.zone |
要确定检索到的区域,我们检查其元数据映射中键下的值。ServiceInstance "zone" |
筛选检索到的实例,并仅返回同一区域中的实例。
如果区域是或同一区域中没有实例,则返回所有检索到的实例。ZonePreferenceServiceInstanceListSupplier
null
为了使用基于区域的负载平衡方法,您必须在自定义配置中实例化 bean。ZonePreferenceServiceInstanceListSupplier
我们使用委托来处理 bean。
我们建议使用委托,用 包装它以利用 LoadBalancer 缓存机制,然后在 的构造函数中传递生成的 Bean。ServiceInstanceListSupplier
DiscoveryClientServiceInstanceListSupplier
CachingServiceInstanceListSupplier
ZonePreferenceServiceInstanceListSupplier
您可以使用此示例配置进行设置:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withCaching()
.withZonePreference()
.build(context);
}
}
3.5. LoadBalancer 的实例运行状况检查
可以为 LoadBalancer 启用计划的 HealthCheck。为此提供了 。它会定期验证委托提供的实例是否仍然有效,并且只返回运行状况良好的实例。
除非没有 - 否则它将返回所有检索到的实例。HealthCheckServiceInstanceListSupplier
ServiceInstanceListSupplier
在使用 .对于
客户端,则没有必要使用,因为我们已经得到了
在查询外部 ServiceDiscovery 后运行正常的实例。SimpleDiscoveryClient |
对于每个服务具有少量实例的设置,还建议使用此供应商 以避免对失败的实例重试调用。 |
如果使用任何 Service Discovery 支持的供应商,通常不需要添加此运行状况检查机制,因为我们直接检索实例的运行状况 从 Service Registry 中。 |
这依赖于 delegate flux 提供的更新实例。在极少数情况下,当您希望使用不刷新实例的委托时,即使实例列表可能会更改(例如我们提供的列表),也可以设置为由 .然后,您还可以通过修改的值来调整 refretch 间隔,并通过设置为 as every instances refetch 来选择禁用额外的运行状况检查重复
也会触发 HealthCheck。HealthCheckServiceInstanceListSupplier DiscoveryClientServiceInstanceListSupplier spring.cloud.loadbalancer.health-check.refetch-instances true HealthCheckServiceInstanceListSupplier spring.cloud.loadbalancer.health-check.refetch-instances-interval spring.cloud.loadbalancer.health-check.repeat-health-check false |
HealthCheckServiceInstanceListSupplier
使用前缀为 的属性。您可以为计划程序设置 和 。您可以通过设置
属性的值。您还可以通过设置属性的值来为任何给定服务设置特定值,并将其替换为服务的正确 ID。如果未指定,则默认使用。如果 the 值设置为 the 或为空,则不会执行运行状况检查。您还可以通过设置 的值来为运行状况检查请求设置自定义端口。如果未设置,则为服务实例上请求的服务可用的端口。spring.cloud.loadbalancer.health-check
initialDelay
interval
spring.cloud.loadbalancer.health-check.path.default
spring.cloud.loadbalancer.health-check.path.[SERVICE_ID]
[SERVICE_ID]
[SERVICE_ID]
/actuator/health
[SERVICE_ID]
null
spring.cloud.loadbalancer.health-check.port
如果您依赖默认路径 (),请确保添加到协作者的依赖项,除非您打算自行添加此类终端节点。/actuator/health spring-boot-starter-actuator |
为了使用运行状况检查调度程序方法,您必须在自定义配置中实例化 bean。HealthCheckServiceInstanceListSupplier
我们使用委托来处理 bean。
我们建议在 .ServiceInstanceListSupplier
DiscoveryClientServiceInstanceListSupplier
HealthCheckServiceInstanceListSupplier
您可以使用此示例配置进行设置:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withHealthChecks()
.build(context);
}
}
对于非反应式堆栈,使用 .
您还可以传递自己的 OR 实例以用于检查。withBlockingHealthChecks() WebClient RestTemplate |
HealthCheckServiceInstanceListSupplier 有自己的基于 Reactor Flux 的缓存机制。因此,如果正在使用它,您可能希望跳过用 .replay() CachingServiceInstanceListSupplier |
在创建自己的配置时,请确保将其放在层次结构中,直接位于通过网络检索实例的供应商之后,例如,在任何其他筛选供应商之前。HealthCheckServiceInstanceListSupplier DiscoveryClientServiceInstanceListSupplier |
3.6. LoadBalancer 的相同实例首选项
您可以设置 LoadBalancer,使其首选之前选择的实例(如果该实例可用)。
为此,您需要使用 .你可以通过将值设置为 to 或通过提供你自己的 bean 来配置它——例如:SameInstancePreferenceServiceInstanceListSupplier
spring.cloud.loadbalancer.configurations
same-instance-preference
ServiceInstanceListSupplier
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withSameInstancePreference()
.build(context);
}
}
这也是 Zookeeper 的替代品。StickyRule |
3.7. LoadBalancer 的基于请求的粘性会话
您可以设置 LoadBalancer,使其首选在请求 Cookie 中提供的实例。如果请求通过 SC LoadBalancer 交换筛选条件函数和筛选条件使用的 或 传递到 LoadBalancer,我们目前支持此功能。instanceId
ClientRequestContext
ServerHttpRequestContext
为此,您需要使用 .你可以通过将值设置为 to 或通过提供你自己的 bean 来配置它——例如:RequestBasedStickySessionServiceInstanceListSupplier
spring.cloud.loadbalancer.configurations
request-based-sticky-session
ServiceInstanceListSupplier
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withRequestBasedStickySession()
.build(context);
}
}
对于该功能,在转发请求之前更新所选服务实例(如果该实例不可用,则可能与原始请求 Cookie 中的服务实例不同)非常有用。为此,请将 的值设置为 。spring.cloud.loadbalancer.sticky-session.add-service-instance-cookie
true
默认情况下,Cookie 的名称为 。您可以通过更改属性的值来修改它。sc-lb-instance-id
spring.cloud.loadbalancer.instance-id-cookie-name
WebClient 支持的负载均衡目前支持此功能。 |
3.8. Spring Cloud LoadBalancer 提示
Spring Cloud LoadBalancer 允许您设置传递给对象内 LoadBalancer 的提示,这些提示稍后可以在可以处理它们的实现中使用。String
Request
ReactiveLoadBalancer
您可以通过设置属性的值来为所有服务设置默认提示。您还可以设置特定值
对于任何给定的服务,通过设置属性的值,替换为服务的正确 ID。如果用户未设置提示,则使用 Hint。spring.cloud.loadbalancer.hint.default
spring.cloud.loadbalancer.hint.[SERVICE_ID]
[SERVICE_ID]
default
3.9. 基于 Hint 的负载均衡
我们还提供了一个 ,它是基于提示的实例选择的实现。HintBasedServiceInstanceListSupplier
ServiceInstanceListSupplier
HintBasedServiceInstanceListSupplier
检查提示请求标头(默认标头名称为 ,但您可以通过更改属性的值来修改它),如果找到提示请求标头,则使用标头中传递的提示值来筛选服务实例。X-SC-LB-Hint
spring.cloud.loadbalancer.hint-header-name
如果未添加提示标头,则使用 properties 中的提示值来筛选服务实例。HintBasedServiceInstanceListSupplier
如果未通过 header 或 properties 设置提示,则返回委托提供的所有服务实例。
筛选时,查找在其 .如果未找到匹配的实例,则返回委托提供的所有实例。HintBasedServiceInstanceListSupplier
hint
metadataMap
您可以使用以下示例配置进行设置:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withCaching()
.withHints()
.build(context);
}
}
3.10. 转换负载均衡的 HTTP 请求
您可以使用 selected 来转换负载均衡的 HTTP 请求。ServiceInstance
对于 ,您需要按如下方式实现和定义:RestTemplate
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 的顺序应用它们。
或者,您可以使用 or 指定顺序。LoadBalancerRequestTransformer.DEFAULT_ORDER
LoadBalancerClientRequestTransformer.DEFAULT_ORDER
3.11. Spring Cloud LoadBalancer Starters
我们还提供了一个Starters,允许您在 Spring Boot 应用程序中轻松添加 Spring Cloud LoadBalancer。
要使用它,只需在构建文件中添加到 Spring Cloud 依赖项即可。org.springframework.cloud:spring-cloud-starter-loadbalancer
Spring Cloud LoadBalancer Starters包括 Spring Boot Caching 和 Evictor。 |
3.12. 传递您自己的 Spring Cloud LoadBalancer 配置
您还可以使用注释来传递自己的负载均衡器客户端配置,传递负载均衡器客户端的名称和配置类,如下所示:@LoadBalancerClient
@Configuration
@LoadBalancerClient(value = "stores", configuration = CustomLoadBalancerConfiguration.class)
public class MyConfiguration {
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}
}
为了更轻松地处理您自己的 LoadBalancer 配置,我们在类中添加了一个方法。builder() ServiceInstanceListSupplier |
您还可以通过将 property 的值设置为 to use with caching 或 to use with caching,使用我们的替代预定义配置来代替默认配置。spring.cloud.loadbalancer.configurations zone-preference ZonePreferenceServiceInstanceListSupplier health-check HealthCheckServiceInstanceListSupplier |
您可以使用此功能来实例化 or 的不同实现,这些实现由您编写,或由我们作为替代项提供(例如 ),以覆盖默认设置。ServiceInstanceListSupplier
ReactorLoadBalancer
ZonePreferenceServiceInstanceListSupplier
您可以在此处查看自定义配置的示例。
annotation 参数(在上面的示例中)指定了我们应该使用给定自定义配置将请求发送到的服务的服务 ID。value stores |
您还可以通过注释传递多个配置(对于多个负载均衡器客户端),如下例所示:@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();
}
}
您传递的类或配置参数不应使用 Comments 或超出组件扫描范围。@LoadBalancerClient @LoadBalancerClients @Configuration |
在创建自己的配置时,如果使用 或 ,请确保使用其中一个配置,而不是同时使用这两个配置,并确保将其直接放在通过网络检索实例的供应商之后,例如,在任何其他筛选供应商之前。CachingServiceInstanceListSupplier HealthCheckServiceInstanceListSupplier DiscoveryClientServiceInstanceListSupplier |
3.13. Spring Cloud LoadBalancer 生命周期
使用自定义 LoadBalancer 配置注册可能有用的一种 bean 类型是 。LoadBalancerLifecycle
这些 bean 提供了名为 、 和 的回调方法,您应该实现这些方法以指定在负载平衡之前和之后应该发生的操作。LoadBalancerLifecycle
onStart(Request<RC> request)
onStartRequest(Request<RC> request, Response<T> lbResponse)
onComplete(CompletionContext<RES, T, RC> completionContext)
onStart(Request<RC> request)
将对象作为参数。
它包含用于选择适当实例的数据,包括下游客户端请求和提示。 还将对象和对象作为参数。
另一方面,为该方法提供了一个对象。
它包含 LoadBalancer ,包括选定的服务实例、针对该服务实例执行的请求和(如果可用)返回到下游客户端的响应,以及(如果发生异常)相应的 .Request
onStartRequest
Request
Response<T>
CompletionContext
onComplete(CompletionContext<RES, T, RC> completionContext)
Response
Status
Throwable
该方法可用于确定有问题的处理器是否处理所提供类型的对象。
如果未被用户覆盖,则返回 .supports(Class requestContextClass, Class responseClass,
Class serverTypeClass)
true
在上述方法调用中,means type 表示客户端响应类型,表示返回的服务器类型。RC RequestContext RES T |
如果您使用的是自定义 HTTP 状态代码,则会收到异常。
为了防止这种情况,您可以设置 的值。
这将导致使用原始状态代码而不是枚举。
然后,将使用 in 字段,但您将能够从该字段中获取原始状态代码。spring.cloud.loadbalancer.use-raw-status-code-in-response-data HttpStatus httpStatus ResponseData rawHttpStatus |
3.14. Spring Cloud LoadBalancer 统计信息
我们提供了一个名为 的 bean,它使用 Micrometer 为负载平衡的调用提供统计信息。LoadBalancerLifecycle
MicrometerStatsLoadBalancerLifecycle
为了将此 bean 添加到应用程序上下文中,请将该值设置为 to 并具有可用(例如,通过将 Spring Boot Actuator 添加到项目中)。spring.cloud.loadbalancer.stats.micrometer.enabled
true
MeterRegistry
MicrometerStatsLoadBalancerLifecycle
在 中注册以下仪表:MeterRegistry
-
loadbalancer.requests.active
:一个仪表,允许您监控任何服务实例的当前活动请求数(通过标签提供的服务实例数据); -
loadbalancer.requests.success
:一个计时器,用于测量任何负载均衡请求的执行时间,这些请求以将响应传递给底层客户端而告终; -
loadbalancer.requests.failed
:一个计时器,用于测量以异常结束的任何负载均衡请求的执行时间; -
loadbalancer.requests.discard
:一个计数器,用于测量丢弃的负载均衡请求的数量,即 LoadBalancer 尚未检索用于运行请求的服务实例的请求。
有关服务实例、请求数据和响应数据的其他信息会在可用时通过标签添加到指标中。
对于某些实现,例如 ,请求和响应数据可能不可用,因为我们从参数建立泛型类型,并且可能无法确定类型和读取数据。BlockingLoadBalancerClient |
当为给定计量器添加至少一条记录时,计量器将在注册表中注册。 |
您可以通过添加 MeterFilters 来进一步配置这些指标的行为(例如,添加发布百分位数和直方图)。 |
3.15. 配置单个 LoadBalancerClient
单个 Loadbalancer 客户端可以单独配置不同的前缀,其中 clientId
是负载均衡器的名称。可以在spring.cloud.loadbalancer
中设置默认配置值。namespace 中,并将与优先的客户端特定值合并spring.cloud.loadbalancer.clients.<clientId>.
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
- 全局启用或禁用负载均衡重试。如果全局启用它,您仍然可以使用 -prefixed 属性禁用特定客户端的重试,但不能反之client
-
spring.cloud.loadbalancer.cache.enabled
- 全局启用或禁用 LoadBalancer 缓存。如果全局启用它,您仍然可以通过创建不包含 delegates 层次结构中的 the 的自定义配置来禁用特定客户端的缓存,但反之则不然。CachingServiceInstanceListSupplier
ServiceInstanceListSupplier
-
spring.cloud.loadbalancer.stats.micrometer.enabled
- 全局启用或禁用 LoadBalancer Micrometer 指标
对于已使用 maps 的属性,您可以在不使用关键字的情况下为每个客户端指定不同的值(例如 , , ),我们保留了该行为,以保持库向后兼容。它将在下一个主要版本中进行修改。clients hints health-check.path |
从 开始,我们在 中引入了标志。如果此标志设置为 ,则将实施方法以调用可从尚未实现该方法的可分配的类,并排除 和 ,在完成任何基于请求的筛选之前,供应商通过网络执行实例检索后,应将其直接放置在实例供应商层次结构中。但是,该标志设置为 default ,因为它将设置为 by default。3.1.7 callGetWithRequestOnDelegates LoadBalancerProperties true ServiceInstanceListSupplier#get(Request request) delegate.get(request) DelegatingServiceInstanceListSupplier CachingServiceInstanceListSupplier HealthCheckServiceInstanceListSupplier 3.1.x false 4.1.0 true |