首页 > 其他分享 >SpringCloud LoadBalancer

SpringCloud LoadBalancer

时间:2023-05-13 17:24:33浏览次数:42  
标签:SpringCloud eureka 实例 loadbalancer jvm spring public LoadBalancer

Spring Cloud提供了自己的客户端负载均衡器抽象和实现。对于负载平衡机制,增加了ReactiveLoadBalancer接口,并为其提供了基于Round RobinRandom的实现。负载均衡策略默认是Round Robin。支持ServiceInstanceListSupplier的基于服务发现的实现,该实现使用类路径中可用的发现客户端从服务发现中检索可用实例

修改负载均衡策略

要修改执行服务的负载均衡策略,配置:

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

}

@LoadBalancerClient的value是服务名,configuration是配置类。

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);
    }
}

修改ReactorLoadBalancer负载均衡实现为RandomLoadBalancer。启动端口为8002,8004的两个Producer,访问http://localhost:8500/producer/hello,多访问几次,可以看到负载均衡改为随机。要自定义负载均衡策略,只需实现ReactiveLoadBalancer接口。

 

RestTemplate和WebClient要使用LoadBalancer作为负载均衡,只需加 @LoadBalanced,如:

@Configuration
public class MyConfiguration {

    @LoadBalanced
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}


@Configuration
public class MyConfiguration {

    @Bean
    @LoadBalanced
    public WebClient.Builder loadBalancedWebClientBuilder() {
        return WebClient.builder();
    }
}

ServiceInstanceListSupplier

ServiceInstanceListSupplier从DiscoveryClient获取服务实例。

CachingServiceInstanceListSupplier

CachingServiceInstanceListSupplier缓存了服务实例,首先从缓存中查找服务,如果没有再从DiscoveryClientServiceInstanceListSupplier查找。CachingServiceInstanceListSupplier默认使用DefaultLoadBalancerCache。如果类路径下有com.github.ben-manes.caffeine:caffeine,则使用Caffeine作为缓存。缓存配置如下:

spring:
  cloud:
    loadbalancer:
      cache:
        enabled: true
        capacity: 256
        ttl: 35s
        caffeine:
          spec: 

enabled表示是否启用cache,默认为true,capacity表示缓存初始容量,默认256。ttl表示缓存过期时间,默认35秒。caffeine.spec是caffeine的配置属性。如果注册中心客户端自带了缓存,比如Eureka,不需要开启CachingServiceInstanceListSupplier,避免双重缓存。

ZonePreferenceServiceInstanceListSupplier

为了实现基于区域的负载平衡,提供了ZoneReferenceServiceInstanceListSupplier。使用DiscoveryClient特定的区域配置(例如,eureka.instance.metadata-map.zone)来选择客户端尝试为其筛选可用服务实例的区域。ZoneReferenceServiceInstanceListSupplier过滤检索到的实例,并且只返回同一区域内的实例。如果区域为null或同一区域内没有实例,则返回所有检索到的实例。比如为Producer服务配置:

public class CustomLoadBalancerConfiguration {

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

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

修改Producer,增加多个服务,端口为8002的application.properties配置:

server.port=8002

spring.application.name=producer

eureka.client.service-url.defaultZone=http://user:123@localhost:8761/eureka/

eureka.instance.metadata-map.zone=区域1

端口为8004的application.properties配置:

server.port=8004

spring.application.name=producer

eureka.client.service-url.defaultZone=http://user:123@localhost:8761/eureka/

eureka.instance.metadata-map.zone=区域1

端口为8006的application.properties配置:

server.port=8006

spring.application.name=producer

eureka.client.service-url.defaultZone=http://user:123@localhost:8761/eureka/

eureka.instance.metadata-map.zone=区域2

分别启动上面3个Producer服务。访问http://localhost:8500/producer/hello,只看到端口为8002和8004。

HealthCheckServiceInstanceListSupplier

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

public class CustomLoadBalancerConfiguration {

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

配置参数由HealthCheck提供:

private Duration initialDelay = Duration.ZERO;

private Duration interval = Duration.ofSeconds(25);

private Duration refetchInstancesInterval = Duration.ofSeconds(25);

private Map<String, String> path = new LinkedCaseInsensitiveMap<>();

private Integer port;


private boolean refetchInstances = false;

	
private boolean repeatHealthCheck = true;

initialDelay是HealthCheck计划程序的初始延迟值。interval是运行HealthCheck计划程序的间隔。refetchInstancesInterval是重新刷新可用服务实例的间隔。path是检查健康状态的路径。可以根据serviceId进行设置。也可以设置默认值。如果没有设置,将使用/actuator/health。port是健康检查的端口。refetchInstances指示服务实例是否应由HealthCheckServiceInstanceListSupplier重新获取。repeatHealthCheck指示是否应继续重复运行状况检查。

SameInstancePreferenceServiceInstanceListSupplier

SameInstancePreferenceServiceInstanceListSupplier优先选择以前的服务实例。配置如下:

public class CustomLoadBalancerConfiguration {

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

通过Cookie值选择服务实例。Cookie名是 sc-lb-instance-id,可以通过spring.cloud.loadbalancer.instance-id-cookie-name改变Cookie名。配置如下:

public class CustomLoadBalancerConfiguration {

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

Spring Cloud LoadBalancer允许设置String提示,这些提示将在Request对象中传递给LoadBalancers在ReactiveLoadBalanceer的实现中使用。通过设置spring.cloud.loadbalancer.hint.defect属性的值,可以为所有服务设置默认提示。还可以通过设置spring.cloud.loadbalancer.hint.[service_ID]属性的值,将[service_ID]替换为服务的正确ID,为任何给定服务设置特定值。如果提示不是由用户设置的,则使用默认值。

 

HintBasedServiceInstanceListSupplier检查提示请求标头(默认标头名称为X-SC-LB-hint,可以通过更改spring.cloud.loadbalancer.hint-header-name属性的值来修改它),如果找到提示请求标头,则使用标头中传递的提示值来筛选服务实例。如果没有添加提示头,HintBasedServiceInstanceListSupplier将使用属性中的提示值来筛选服务实例。如果没有通过标头或属性设置任何提示,则会返回委托提供的所有服务实例。

 

筛选时,HintBasedServiceInstanceListSupplier会在元数据映射中查找在提示键下设置了匹配值的服务实例。如果找不到匹配的实例,则返回委托提供的所有实例。

 

配置如下:

public class CustomLoadBalancerConfiguration {

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

application.yml配置:

spring:
  cloud:
    loadbalancer:
      hint:
        producer: abcd

配置Producer服务的提示为abcd

 

修改Producer,增加多个服务,端口为8002的application.properties配置:

server.port=8002

spring.application.name=producer

eureka.client.service-url.defaultZone=http://user:123@localhost:8761/eureka/

eureka.instance.metadata-map.hint=abcd

端口为8004的application.properties配置:

server.port=8004

spring.application.name=producer

eureka.client.service-url.defaultZone=http://user:123@localhost:8761/eureka/

eureka.instance.metadata-map.hint=abcd

端口为8006的application.properties配置:

server.port=8006

spring.application.name=producer

eureka.client.service-url.defaultZone=http://user:123@localhost:8761/eureka/

eureka.instance.metadata-map.hint=abcde

分别启动上面3个Producer服务。访问http://localhost:8500/producer/hello,只看到端口为8002和8004。

LoadBalancerLifecycle

LoadBalancerLifecycle是LoadBalancer生命周期接口,允许定义在负载平衡之前和之后应该执行的操作。

default boolean supports(Class requestContextClass, Class responseClass, Class serverTypeClass) {
	return true;
}

void onStart(Request<RC> request);

void onStartRequest(Request<RC> request, Response<T> lbResponse);

void onComplete(CompletionContext<RES, T, RC> completionContext);

supports判断是否应该执行生命周期bean的回调。onStart是在负载平衡之前执行的回调方法。onStartRequest是在选择服务实例之后,在执行实际负载平衡请求之前执行的回调方法。onComplete是负载平衡后执行的回调方法。

例子:

@Bean
public LoadBalancerLifecycle loadBalancerLifecycle() {
    return new LoadBalancerLifecycle() {
        @Override
        public void onStart(Request request) {
            System.out.println("start");
        }

        @Override
        public void onStartRequest(Request request, Response lbResponse) {
            System.out.println("onStartRequest");
        }

        @Override
        public void onComplete(CompletionContext completionContext) {
            System.out.println("onComplete");
        }
    };
}

访问http://localhost:8500/producer/hello,看到

start
onStartRequest
onComplete

MicrometerStatsLoadBalancerLifecycle

提供了一个名为MicrometerStatsLoadBalancerLifecycle的LoadBalancer生命周期bean,它使用Micrometer为负载平衡调用提供统计信息。

MicrometerStatsLoadBalancerLifecycle在MeterRegistry中注册以下仪表:

  • loadbalancer.requests.active: 任何服务实例的当前活动请求数量
  • loadbalancer.requests.success:任何服务实例的请求成功数量
  • loadbalancer.requests.failed:任何服务实例的请求失败数量
  • loadbalancer.requests.discard:任何服务实例的请求丢弃数量

 

添加依赖:

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

在application.yml配置:

spring:
  cloud:
    loadbalancer:
      stats:
        micrometer:
          enabled: true

management:
  endpoints:
   web:
    exposure:
     include: '*'

开启Micrometer指标收集。

 

访问http://localhost:8500/producer/hello后,在访问http://localhost:8500/actuator/metrics,看到:

{
    "names": [
        "application.ready.time", 
        "application.started.time", 
        "disk.free", 
        "disk.total", 
        "executor.active", 
        "executor.completed", 
        "executor.pool.core", 
        "executor.pool.max", 
        "executor.pool.size", 
        "executor.queue.remaining", 
        "executor.queued", 
        "http.server.requests", 
        "jvm.buffer.count", 
        "jvm.buffer.memory.used", 
        "jvm.buffer.total.capacity", 
        "jvm.classes.loaded", 
        "jvm.classes.unloaded", 
        "jvm.gc.live.data.size", 
        "jvm.gc.max.data.size", 
        "jvm.gc.memory.allocated", 
        "jvm.gc.memory.promoted", 
        "jvm.gc.overhead", 
        "jvm.gc.pause", 
        "jvm.memory.committed", 
        "jvm.memory.max", 
        "jvm.memory.usage.after.gc", 
        "jvm.memory.used", 
        "jvm.threads.daemon", 
        "jvm.threads.live", 
        "jvm.threads.peak", 
        "jvm.threads.states", 
        "loadbalancer.requests.active", 
        "loadbalancer.requests.success", 
        "logback.events", 
        "process.cpu.usage", 
        "process.files.max", 
        "process.files.open", 
        "process.start.time", 
        "process.uptime", 
        "spring.cloud.gateway.requests", 
        "spring.cloud.gateway.routes.count", 
        "system.cpu.count", 
        "system.cpu.usage", 
        "system.load.average.1m"
    ]
}

可以看到loadbalancer.requests.active,loadbalancer.requests.success两个参数。在访问http://localhost:8500/actuator/metrics/loadbalancer.requests.success,看到:

{
    "name": "loadbalancer.requests.success", 
    "description": null, 
    "baseUnit": "seconds", 
    "measurements": [
        {
            "statistic": "COUNT", 
            "value": 1
        }, 
        {
            "statistic": "TOTAL_TIME", 
            "value": 3.853133232
        }, 
        {
            "statistic": "MAX", 
            "value": 0
        }
    ], 
    "availableTags": [
        {
            "tag": "serviceInstance.host", 
            "values": [
                "192.168.31.148"
            ]
        }, 
        {
            "tag": "serviceInstance.port", 
            "values": [
                "8002"
            ]
        }, 
        {
            "tag": "serviceInstance.instanceId", 
            "values": [
                "192.168.31.148:producer:8002"
            ]
        }, 
        {
            "tag": "method", 
            "values": [
                "GET"
            ]
        }, 
        {
            "tag": "serviceId", 
            "values": [
                "PRODUCER"
            ]
        }, 
        {
            "tag": "uri", 
            "values": [
                "/hello"
            ]
        }, 
        {
            "tag": "outcome", 
            "values": [
                "SUCCESS"
            ]
        }, 
        {
            "tag": "status", 
            "values": [
                "200"
            ]
        }
    ]
}

标签:SpringCloud,eureka,实例,loadbalancer,jvm,spring,public,LoadBalancer
From: https://www.cnblogs.com/shigongp/p/17397145.html

相关文章

  • 创建SpringCloud项目
    SpringCloud简介SpringCloud是目前国内使用最广泛的微服务框架。SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验。SpringCloud常用组件1.服务注册发现:Eureka,Nacos,Consul2.服务远程调用:OpenFeign,Dubbo3.服务链路......
  • SpringCloud之Zookeeper作为配置中心
    Zookeeper提供了一个分层的命名空间,让客户端可以存储任意数据,例如配置数据。SpringCloudZookeeperConfig是ConfigServer和Client的替代方案。在特殊的“bootstrap”阶段,配置被加载到Spring环境中。默认情况下,配置存储在/config命名空间中。将根据应用程序的名称和活动配置文件......
  • [SpringCloud]Spring-Cloud-Gateway之启动过程(源码分析)
    1前言1.1环境信息Spring-Cloud-Gateway:2.2.9.RELEASEorg.springframework.boot:spring-boot:2.3.12.RELEASEio.projectreactor.netty:reactor-netty:0.9.20.RELEASEio.netty:netty-transport:4.1.65.FINAL2启动过程#与Netty的调用链路2.1简版(V1.0)cn.seres.b......
  • SpringCloud之Zookeeper作为注册中心
    SpringCloudZookeeper通过自动配置和绑定到Spring环境,为SpringBoot应用程序提供ApacheZookeepper集成。通过一些简单的注释,可以快速启用和配置应用程序中的常见模式,并使用Zookeeper构建大型分布式系统。提供的模式包括服务发现和分布式配置。 特征服务发现:可以向Zookeepe......
  • SpringCloud Hoxton——Consul服务注册与发现
    1.开篇Consul是什么?Consul是一套开源的分布式服务发现和配置管理系统,由HashiCorp公司用Go语言开发。提供了微服务系统中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格,总之Consul提供了一种完整的服务......
  • SpringCloud gateway Actuator
    要启用gateway的Actuator交互首先添加依赖:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>其次在application.properties配置:management.end......
  • SpringCloud gateway 元数据,超时,Netty Access Logs
    元数据spring:cloud:gateway:routes:-id:route_with_metadatauri:https://example.orgmetadata:optionName:"OptionValue"compositeObject:name:"value"iAmNu......
  • SpringCloud gateway HttpHeadersFilters
    HttpHeadersFilter在将请求发送到下游之前应用于请求,例如在NettyRoutingFilter中。1、ForwardedHeadersFilterForwardedHeadersFilter创建一个Forwarded标头以发送到下游服务。它将当前请求的Host标头、scheme和端口添加到任何现有的Forwarded标头中。2、RemoveHopByHopH......
  • SpringCloud gateway全局过滤器
    GlobalFilter接口具有与GatewayFilter相同的签名。这些是有条件地应用于所有路由的特殊过滤器。组合GlobalFilter和GatewayFilter当请求与路由匹配时,过滤web处理程序会将GlobalFilter的所有实例和GatewayFilter的所有路由特定实例添加到过滤器链中。这个组合的过滤器链由org.spr......
  • SpringCloud gateway内置过滤器之六
    1、RequestSizeGatewayFilter当请求大小大于允许的限制时,RequestSizeGatewayFilter可以限制请求到达下游服务。过滤器采用maxSize参数。maxSize是`DataSize类型,因此可以将值定义为一个数字,后跟可选的DataUnit后缀,如“KB”或“MB”。字节的默认值为“B”。它是以字节为单位定义......