3. Spring Cloud 负载均衡器

Spring Cloud 提供了自己的客户端负载均衡器抽象和实现。对于负载均衡 机制ReactiveLoadBalancer添加了接口,并添加了基于 Round-RobinRandom 的实现 已经为此提供了。为了从 reactive 中选择实例ServiceInstanceListSupplier被使用。目前,我们支持基于服务发现的ServiceInstanceListSupplier,它使用 Classpath 中可用的 Discovery Client 从 Service Discovery 中检索可用实例。spring-doc.cadn.net.cn

可以通过设置spring.cloud.loadbalancer.enabledfalse.

3.1. 在负载均衡算法之间切换

ReactiveLoadBalancerimplementation 的默认 implementation 是RoundRobinLoadBalancer.要切换到其他实现,无论是针对所选服务还是所有服务,您可以使用自定义 LoadBalancer 配置机制spring-doc.cadn.net.cn

例如,以下配置可以通过@LoadBalancerClient注解切换到使用RandomLoadBalancer:spring-doc.cadn.net.cn

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);
    }
}
您作为@LoadBalancerClient@LoadBalancerClients配置参数不应使用@Configuration或位于组件扫描范围之外。

3.2. Spring Cloud LoadBalancer 集成

为了方便使用 Spring Cloud LoadBalancer,我们提供了ReactorLoadBalancerExchangeFilterFunction,可以与WebClientBlockingLoadBalancerClient这适用于RestTemplate. 您可以在以下部分中查看详细信息和使用示例:spring-doc.cadn.net.cn

3.3. Spring Cloud LoadBalancer 缓存

除了基本的ServiceInstanceListSupplier实现,通过DiscoveryClient每次它必须选择一个实例时,我们都会提供两个缓存实现。spring-doc.cadn.net.cn

3.3.1. Caffeine 支持的 LoadBalancer 缓存实现

如果你有com.github.ben-manes.caffeine:caffeine在 classpath 中,将使用基于 Caffeine 的 implementation 。 有关如何配置它的信息,请参阅 LoadBalancerCacheConfiguration 部分。spring-doc.cadn.net.cn

如果您使用的是咖啡因,您还可以通过在spring.cloud.loadbalancer.cache.caffeine.spec财产。spring-doc.cadn.net.cn

警告:传递您自己的 Caffeine 规范将覆盖任何其他 LoadBalancerCache 设置,包括常规 LoadBalancer 缓存配置字段,例如ttlcapacity.spring-doc.cadn.net.cn

3.3.2. 默认 LoadBalancer 缓存实现

如果类路径中没有 Caffeine,则DefaultLoadBalancerCache,它自动随spring-cloud-starter-loadbalancer。 有关如何配置它的信息,请参阅 LoadBalancerCacheConfiguration 部分。spring-doc.cadn.net.cn

要使用 Caffeine 而不是默认缓存,请添加com.github.ben-manes.caffeine:caffeine依赖于 Classpath 的 classpath 中。

3.3.3. LoadBalancer 缓存配置

您可以设置自己的ttl值(写入后的时间,在此时间之后条目应过期),表示为Duration,通过传递String符合Spring BootStringDuration转换器语法. 作为spring.cloud.loadbalancer.cache.ttl财产。 您还可以通过设置spring.cloud.loadbalancer.cache.capacity财产。spring-doc.cadn.net.cn

默认设置包括ttl设置为 35 秒,默认值initialCapacity256.spring-doc.cadn.net.cn

您还可以通过设置spring.cloud.loadbalancer.cache.enabledfalse.spring-doc.cadn.net.cn

尽管基本的非缓存实现对于原型设计和测试很有用,但它的效率远低于缓存版本,因此我们建议在生产中始终使用缓存版本。如果缓存已由DiscoveryClientimplementation 等EurekaDiscoveryClient,则应禁用负载均衡器缓存以防止双重缓存。
当您创建自己的配置时,如果您使用CachingServiceInstanceListSupplier确保将其直接放在层次结构中,在通过网络检索实例的供应商之后,例如DiscoveryClientServiceInstanceListSupplier,先于任何其他筛选供应商。

3.4. 基于区域的负载均衡

为了实现基于区域的负载均衡,我们提供了ZonePreferenceServiceInstanceListSupplier. 我们使用DiscoveryClient-特定zone配置(例如eureka.instance.metadata-map.zone) 选择客户端尝试筛选可用服务实例的区域。spring-doc.cadn.net.cn

您还可以覆盖DiscoveryClient-specific zone 设置,方法是将spring.cloud.loadbalancer.zone财产。
目前,只有 Eureka Discovery Client 被检测来设置 LoadBalancer 区域。对于其他发现客户端,请将spring.cloud.loadbalancer.zone财产。更多仪器即将推出。
确定检索到的ServiceInstance,我们检查"zone"键。

ZonePreferenceServiceInstanceListSupplier筛选检索到的实例,并仅返回同一区域中的实例。 如果区域为null或者同一区域内没有实例,则返回所有检索到的实例。spring-doc.cadn.net.cn

为了使用基于区域的负载均衡方法,您必须实例化一个ZonePreferenceServiceInstanceListSupplierbean 的 bean 进行自定义配置spring-doc.cadn.net.cn

我们使用委托人ServiceInstanceListSupplier豆。 我们建议使用DiscoveryClientServiceInstanceListSupplierdelegate,用CachingServiceInstanceListSupplier来利用 LoadBalancer 缓存机制,然后在ZonePreferenceServiceInstanceListSupplier.spring-doc.cadn.net.cn

您可以使用此示例配置进行设置:spring-doc.cadn.net.cn

public class CustomLoadBalancerConfiguration {

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

3.5. LoadBalancer 的实例运行状况检查

可以为 LoadBalancer 启用计划的 HealthCheck。这HealthCheckServiceInstanceListSupplier为此提供了。它会定期验证委托提供的实例ServiceInstanceListSupplier仍处于活动状态,并且仅返回运行状况良好的实例, 除非没有 - 否则它将返回所有检索到的实例。spring-doc.cadn.net.cn

在使用SimpleDiscoveryClient.对于 客户端,则没有必要使用,因为我们已经得到了 在查询外部 ServiceDiscovery 后运行正常的实例。
对于每个服务具有少量实例的设置,还建议使用此供应商 以避免对失败的实例重试调用。
如果使用任何 Service Discovery 支持的供应商,通常不需要添加此运行状况检查机制,因为我们直接检索实例的运行状况 从 Service Registry 中。
HealthCheckServiceInstanceListSupplier依赖于 Delegate Flux 提供的更新实例。在极少数情况下,当您想使用不刷新实例的委托时,即使实例列表可能会更改(例如DiscoveryClientServiceInstanceListSupplier由我们提供),您可以设置spring.cloud.loadbalancer.health-check.refetch-instancestrue要让HealthCheckServiceInstanceListSupplier.然后,您还可以通过修改spring.cloud.loadbalancer.health-check.refetch-instances-interval并选择禁用额外的 HealthCheck 重复项,方法是将spring.cloud.loadbalancer.health-check.repeat-health-checkfalse因为每个实例都会重新获取 也会触发 HealthCheck。

HealthCheckServiceInstanceListSupplier使用前缀为spring.cloud.loadbalancer.health-check.您可以设置initialDelayinterval对于调度程序。您可以通过设置 的spring.cloud.loadbalancer.health-check.path.default财产。您还可以通过设置spring.cloud.loadbalancer.health-check.path.[SERVICE_ID]property, 替换[SERVICE_ID]替换为您的服务的正确 ID。如果[SERVICE_ID]未指定,/actuator/health默认使用。如果[SERVICE_ID]设置为null或 empty 的值,则不会执行运行状况检查。您还可以通过设置spring.cloud.loadbalancer.health-check.port.如果未设置,则为服务实例上请求的服务可用的端口。spring-doc.cadn.net.cn

如果您依赖默认路径 (/actuator/health),请确保添加spring-boot-starter-actuator添加到协作者的依赖项中,除非您打算自行添加此类终端节点。

要使用运行状况检查计划程序方法,您必须实例化HealthCheckServiceInstanceListSupplierbean 的 bean 进行自定义配置spring-doc.cadn.net.cn

我们使用委托人ServiceInstanceListSupplier豆。 我们建议传递一个DiscoveryClientServiceInstanceListSupplierdelegate 的构造函数HealthCheckServiceInstanceListSupplier.spring-doc.cadn.net.cn

您可以使用此示例配置进行设置:spring-doc.cadn.net.cn

public class CustomLoadBalancerConfiguration {

    @Bean
    public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
        return ServiceInstanceListSupplier.builder()
                    .withDiscoveryClient()
                    .withHealthChecks()
                    .build(context);
        }
    }
对于非反应式堆栈,使用withBlockingHealthChecks(). 您也可以将自己的WebClientRestTemplate实例。
HealthCheckServiceInstanceListSupplier拥有自己的基于 Reactor Flux 的缓存机制replay().因此,如果正在使用它,您可能希望跳过用CachingServiceInstanceListSupplier.
当您创建自己的配置时,HealthCheckServiceInstanceListSupplier,请确保将其直接放置在通过网络检索实例的供应商之后的层次结构中,例如,DiscoveryClientServiceInstanceListSupplier,先于任何其他筛选供应商。

3.6. LoadBalancer 的相同实例首选项

您可以设置 LoadBalancer,使其首选之前选择的实例(如果该实例可用)。spring-doc.cadn.net.cn

为此,您需要使用SameInstancePreferenceServiceInstanceListSupplier.您可以通过设置spring.cloud.loadbalancer.configurationssame-instance-preference或者通过提供您自己的ServiceInstanceListSupplierbean — 例如:spring-doc.cadn.net.cn

public class CustomLoadBalancerConfiguration {

    @Bean
    public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
        return ServiceInstanceListSupplier.builder()
                    .withDiscoveryClient()
                    .withSameInstancePreference()
                    .build(context);
        }
    }
这也是 Zookeeper 的替代品StickyRule.

3.7. LoadBalancer 的基于请求的粘性会话

您可以设置 LoadBalancer,使其首选具有instanceId在请求 Cookie 中提供。如果请求通过ClientRequestContextServerHttpRequestContext,SC LoadBalancer 使用交换筛选函数和筛选条件。spring-doc.cadn.net.cn

为此,您需要使用RequestBasedStickySessionServiceInstanceListSupplier.您可以通过设置spring.cloud.loadbalancer.configurationsrequest-based-sticky-session或者通过提供您自己的ServiceInstanceListSupplierbean — 例如:spring-doc.cadn.net.cn

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-cookietrue.spring-doc.cadn.net.cn

默认情况下,Cookie 的名称为sc-lb-instance-id.您可以通过更改spring.cloud.loadbalancer.instance-id-cookie-name财产。spring-doc.cadn.net.cn

WebClient 支持的负载均衡目前支持此功能。

3.8. Spring Cloud LoadBalancer 提示

Spring Cloud LoadBalancer 允许您设置StringRequest对象,以后可以在ReactiveLoadBalancer可以处理它们的实现。spring-doc.cadn.net.cn

您可以通过设置spring.cloud.loadbalancer.hint.default财产。您还可以设置特定值 对于任何给定的服务,通过设置spring.cloud.loadbalancer.hint.[SERVICE_ID]property, 替换[SERVICE_ID]替换为您的服务的正确 ID。如果 hint 不是由用户设置的,则default被使用。spring-doc.cadn.net.cn

3.9. 基于 Hint 的负载均衡

我们还提供HintBasedServiceInstanceListSupplier,它是一个ServiceInstanceListSupplier实现,用于基于提示的实例选择。spring-doc.cadn.net.cn

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

如果未添加 hint header,则HintBasedServiceInstanceListSupplier使用属性中的提示值来筛选服务实例。spring-doc.cadn.net.cn

如果未通过 header 或 properties 设置提示,则返回委托提供的所有服务实例。spring-doc.cadn.net.cn

过滤时,HintBasedServiceInstanceListSupplier查找在hintmetadataMap.如果未找到匹配的实例,则返回委托提供的所有实例。spring-doc.cadn.net.cn

您可以使用以下示例配置进行设置:spring-doc.cadn.net.cn

public class CustomLoadBalancerConfiguration {

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

3.10. 转换负载均衡的 HTTP 请求

您可以使用选定的ServiceInstance转换负载均衡的 HTTP 请求。spring-doc.cadn.net.cn

RestTemplate,您需要实现并定义LoadBalancerRequestTransformer如下:spring-doc.cadn.net.cn

@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如下:spring-doc.cadn.net.cn

@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_ORDERLoadBalancerClientRequestTransformer.DEFAULT_ORDER以指定顺序。spring-doc.cadn.net.cn

3.11. Spring Cloud LoadBalancer Starters

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

Spring Cloud LoadBalancer Starters包括 Spring Boot CachingEvictor

3.12. 传递您自己的 Spring Cloud LoadBalancer 配置

您还可以使用@LoadBalancerClient注解来传递您自己的负载均衡器客户端配置,并传递负载均衡器客户端的名称和配置类,如下所示:spring-doc.cadn.net.cn

@Configuration
@LoadBalancerClient(value = "stores", configuration = CustomLoadBalancerConfiguration.class)
public class MyConfiguration {

    @Bean
    @LoadBalanced
    public WebClient.Builder loadBalancedWebClientBuilder() {
        return WebClient.builder();
    }
}
为了更轻松地使用您自己的 LoadBalancer 配置,我们添加了一个builder()方法添加到ServiceInstanceListSupplier类。
您还可以使用我们的替代预定义配置来代替默认配置,方法是将spring.cloud.loadbalancer.configurationsproperty 设置为zone-preference使用ZonePreferenceServiceInstanceListSupplier替换为 caching 或 tohealth-check使用HealthCheckServiceInstanceListSupplier与缓存。

您可以使用此功能来实例化ServiceInstanceListSupplierReactorLoadBalancer,由您编写或由我们作为替代方案提供(例如ZonePreferenceServiceInstanceListSupplier) 覆盖默认设置。spring-doc.cadn.net.cn

您可以在此处查看自定义配置的示例。spring-doc.cadn.net.cn

注释value参数 (stores在上面的示例中)指定我们应该使用给定自定义配置将请求发送到的服务的服务 ID。

您还可以通过@LoadBalancerClientsannotation 中,如下例所示:spring-doc.cadn.net.cn

@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();
    }
}
您作为@LoadBalancerClient@LoadBalancerClients配置参数不应使用@Configuration或位于组件扫描范围之外。
当您创建自己的配置时,如果您使用CachingServiceInstanceListSupplierHealthCheckServiceInstanceListSupplier,请确保使用其中一个,而不是同时使用这两个,并确保将其直接放在通过网络检索实例的供应商之后的层次结构中,例如,DiscoveryClientServiceInstanceListSupplier,先于任何其他筛选供应商。

3.13. Spring Cloud LoadBalancer 生命周期

使用自定义 LoadBalancer 配置注册可能有用的一种 bean 类型是LoadBalancerLifecycle.spring-doc.cadn.net.cn

LoadBalancerLifecyclebean 提供名为onStart(Request<RC> request),onStartRequest(Request<RC> request, Response<T> lbResponse)onComplete(CompletionContext<RES, T, RC> completionContext),您应该实施该策略以指定在负载均衡之前和之后应执行的作。spring-doc.cadn.net.cn

onStart(Request<RC> request)采用Requestobject 作为参数。 它包含用于选择适当实例的数据,包括下游客户端请求和提示onStartRequest还采用Requestobject 的 URL 中,此外,Response<T>object 作为参数。 另一方面,一个CompletionContext对象提供给onComplete(CompletionContext<RES, T, RC> completionContext)方法。 它包含 LoadBalancerResponse,包括所选服务实例,则Status对该服务实例执行的请求和(如果可用)返回到下游客户端的响应,以及(如果发生异常)相应的Throwable.spring-doc.cadn.net.cn

supports(Class requestContextClass, Class responseClass, Class serverTypeClass)method 可用于确定相关处理器是否处理所提供类型的对象。 如果未被用户覆盖,则返回true.spring-doc.cadn.net.cn

在前面的方法调用中,RC方法RequestContext类型RES表示客户端响应类型,并且T表示返回的服务器类型。
如果您使用的是自定义 HTTP 状态代码,则会收到异常。 为了防止这种情况,您可以设置spring.cloud.loadbalancer.use-raw-status-code-in-response-data. 这将导致使用原始状态代码而不是HttpStatus枚举。 这httpStatus字段输入ResponseData,但您将能够从rawHttpStatus田。

3.14. Spring Cloud LoadBalancer 统计信息

我们提供LoadBalancerLifecyclebean 调用MicrometerStatsLoadBalancerLifecycle,它使用 Micrometer 为负载均衡调用提供统计信息。spring-doc.cadn.net.cn

为了将此 bean 添加到您的应用程序上下文中,请设置spring.cloud.loadbalancer.stats.micrometer.enabledtrue并具有MeterRegistry可用(例如,通过将 Spring Boot Actuator 添加到您的项目中)。spring-doc.cadn.net.cn

MicrometerStatsLoadBalancerLifecycle在 中注册以下仪表MeterRegistry:spring-doc.cadn.net.cn

  • loadbalancer.requests.active:一个仪表,允许您监控任何服务实例的当前活动请求数(通过标签提供的服务实例数据);spring-doc.cadn.net.cn

  • loadbalancer.requests.success:一个计时器,用于测量任何负载均衡请求的执行时间,这些请求以将响应传递给底层客户端而告终;spring-doc.cadn.net.cn

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

  • loadbalancer.requests.discard:一个计数器,用于测量丢弃的负载均衡请求的数量,即 LoadBalancer 尚未检索用于运行请求的服务实例的请求。spring-doc.cadn.net.cn

有关服务实例、请求数据和响应数据的其他信息会在可用时通过标签添加到指标中。spring-doc.cadn.net.cn

对于某些实现,例如BlockingLoadBalancerClient,请求和响应数据可能不可用,因为我们从参数建立泛型类型,并且可能无法确定类型并读取数据。
当为给定计量器添加至少一条记录时,计量器将在注册表中注册。
您可以通过以下方式进一步配置这些量度的行为(例如,添加发布百分位数和直方图添加MeterFilters.

3.15. 配置单个 LoadBalancerClient

单个 Loadbalancer 客户端可以单独配置不同的前缀spring.cloud.loadbalancer.clients.<clientId>.哪里clientId是 LoadBalancer 的名称。默认配置值可以在spring.cloud.loadbalancer.namespace 中,并将与优先的客户端特定值合并spring-doc.cadn.net.cn

例 5.application.yml
spring:
  cloud:
    loadbalancer:
      health-check:
        initial-delay: 1s
      clients:
        myclient:
          health-check:
            interval: 30s

上面的示例将导致合并的运行状况检查@ConfigurationPropertiesobject 替换为initial-delay=1sinterval=30s.spring-doc.cadn.net.cn

每个客户端的配置属性适用于大多数属性,但以下全局属性除外:spring-doc.cadn.net.cn

  • spring.cloud.loadbalancer.enabled- 全局启用或禁用负载均衡spring-doc.cadn.net.cn

  • spring.cloud.loadbalancer.retry.enabled- 全局启用或禁用负载均衡重试。如果全局启用它,您仍然可以使用client-前缀属性,但不是相反spring-doc.cadn.net.cn

  • spring.cloud.loadbalancer.cache.enabled- 全局启用或禁用 LoadBalancer 缓存。如果全局启用它,您仍然可以通过创建不包含CachingServiceInstanceListSupplierServiceInstanceListSupplierdelegates 层次结构,但不是相反。spring-doc.cadn.net.cn

  • spring.cloud.loadbalancer.stats.micrometer.enabled- 全局启用或禁用 LoadBalancer Micrometer 指标spring-doc.cadn.net.cn

对于已使用映射的属性,您可以为每个客户端指定不同的值,而无需使用clients关键字(例如hints,health-check.path),我们保留了该行为以保持库向后兼容。它将在下一个主要版本中进行修改。
起始3.1.7,我们引入了callGetWithRequestOnDelegates标志输入LoadBalancerProperties.如果此标志设置为true,ServiceInstanceListSupplier#get(Request request)方法将实现以调用delegate.get(request)in classes assignable from (可分配自的类)DelegatingServiceInstanceListSupplier尚未实现该方法,但不包括CachingServiceInstanceListSupplierHealthCheckServiceInstanceListSupplier,在执行任何基于请求的筛选之前,应将其直接放置在供应商通过网络执行实例检索之后的实例供应商层次结构中。为3.1.x该标志设置为false但是,默认情况下,由于4.1.0它将被设置为true默认情况下。