如何应用 Spring Cloud 2020 中重磅举荐的负载均衡器 Spring Cloud LoadBalancer (下文简称 SCL),如何扩大负载平衡策略? 你将从本文中获取到答案

疾速上手 SCL

  • 如果我的项目中想应用 SCL,则仅须要增加如下 maven 依赖即可
<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>
  • SCL 是构建服务发现的根底上,因为目前 Spring Cloud Alibaba 并未兼容 SCL (具体兼容计划能够参考 pig),当然你能够抉择应用Eureka 测试。
  • 若将 RestTemplate 和 客户端负载平衡联合应用,在 bean 定义上减少 @LoadBalanced 注解即可.
@Bean@LoadBalancedpublic RestTemplate restTemplate() {    return new RestTemplate();}

个性化负载平衡策略

  • 目前版本 (spring cloud 2020) 内置轮询、随机的负载平衡策略,默认轮询策略。
  • 当然能够通过 LoadBalancerClient 注解,指定服务级别的负载平衡策略
@LoadBalancerClient(value = "demo-provider", configuration = RandomLoadbalancerConfig.class)
public class RandomLoadbalancerConfig {    @Bean    public ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment,            LoadBalancerClientFactory loadBalancerClientFactory) {        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);        return new RandomLoadBalancer(                loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);    }}

自定义负载平衡策略

  • 通过上文可知,目前 SCL 反对的负载平衡策略相较于 Ribbon 还是较少,须要开发者自行实现,好在 SCL 提供了便捷的 API 不便扩大应用。 这里演示自定义一个基于注册核心元数据的灰度负载平衡策略。
  • 定义灰度负载平衡策略
@Slf4jpublic class GrayRoundRobinLoadBalancer extends RoundRobinLoadBalancer {    private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;    private String serviceId;    @Override    public Mono<Response<ServiceInstance>> choose(Request request) {        ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider                .getIfAvailable(NoopServiceInstanceListSupplier::new);        return supplier.get(request).next().map(serviceInstances -> getInstanceResponse(serviceInstances, request));    }    Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances, Request request) {        // 注册核心无可用实例 抛出异样        if (CollUtil.isEmpty(instances)) {            log.warn("No instance available {}", serviceId);            return new EmptyResponse();        }        DefaultRequestContext requestContext = (DefaultRequestContext) request.getContext();        RequestData clientRequest = (RequestData) requestContext.getClientRequest();        HttpHeaders headers = clientRequest.getHeaders();        String reqVersion = headers.getFirst(CommonConstants.VERSION);        if (StrUtil.isBlank(reqVersion)) {            return super.choose(request).block();        }        // 遍历能够实例元数据,若匹配则返回此实例        for (ServiceInstance instance : instances) {            NacosServiceInstance nacosInstance = (NacosServiceInstance) instance;            Map<String, String> metadata = nacosInstance.getMetadata();            String targetVersion = MapUtil.getStr(metadata, CommonConstants.VERSION);            if (reqVersion.equalsIgnoreCase(targetVersion)) {                log.debug("gray requst match success :{} {}", reqVersion, nacosInstance);                return new DefaultResponse(nacosInstance);            }        }        // 降级策略,应用轮询策略        return super.choose(request).block();    }}
  • 针对客户端注入灰度负载平衡策略
@LoadBalancerClient(value = "demo-provider", configuration = GrayRoundLoadbalancerConfig.class)
  • 服务实例定义版本号

  • 申请携带版本号,测试应用
curl --location --request GET 'http://localhost:6060/req?key=b' \--header 'VERSION: b'

优化负载平衡策略注入

  • 如上文所述,所有的个性化负载策略都须要手动通过 LoadBalancerClient 注入十分的不不便。 咱们能够参考 LoadBalancerClients 的批量注入逻辑结构本人的 BeanRegistrar

public class GrayLoadBalancerClientConfigurationRegistrar implements ImportBeanDefinitionRegistrar {    @Override    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {        Field[] fields = ReflectUtil.getFields(ServiceNameConstants.class);        // 遍历服务名称,注入反对灰度策略的负载均衡器        for (Field field : fields) {            Object fieldValue = ReflectUtil.getFieldValue(ServiceNameConstants.class, field);            registerClientConfiguration(registry, fieldValue, GrayLoadBalancerClientConfiguration.class);        }    }}

>>> 源码 https://gitee.com/log4j/pig,欢送署名转载 <<<