SpringCloud灰度路由

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
应用型负载均衡 ALB,每月750个小时 15LCU
简介: SpringCloud灰度路由

网关

  1. 需要重写filter、LoadBalancerClientFactory、LoadBalancerClientConfiguration、LoadBalancer
  2. 再将filter、LoadBalancerClientFactory配置到spring中
  3. LoadBalancerClientConfiguration需配到spring中,但是不要主动被扫描到(也就是说不要被全局加载)
  4. 由filter做路由拦截,调用LoadBalancerClientFactory获取一个局部的LoadBalancer实例进行服务的筛选
  5. 服务待提供者metadata添加 VERSIONL:版本号 关键信息做区分
  6. 前端调用增加请求头 VERSION=版本号


feign

  1. 需要重写LoadBalancerClientFactory、LoadBalancerClientConfiguration、LoadBalancer
  2. 再将LoadBalancerClientFactory配置到spring中
  3. LoadBalancerClientConfiguration需配到spring中,但是不要主动被扫描到(也就是说不要被全局加载)
  4. 重新注入BlockingLoadBalancerClient,使用新的LoadBalancerClientFactory替换掉原本的Factory
  5. 由原本你的逻辑调用新的LoadBalancerClientFactory获取一个局部的LoadBalancer实例进行服务的筛选
  6. 服务待提供者metadata添加 VERSIONL:版本号 关键信息做区分
  7. feign接口在方法的@RequestMapping注解加上 headers={"VERSION=版本号"} 参数作为筛选


实操
公用的LoadBalancerClientFactory、LoadBalancerClientConfiguration、LoadBalancer

VersionGrayLoadBalancer.java


基于版本控制过滤的轮询,参照原org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer修改的


主要增加选择服务实例前对实例的metadata进行筛选

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.*;
import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.SelectedInstanceCallback;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.http.HttpHeaders;
import reactor.core.publisher.Mono;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@Slf4j
public class VersionGrayLoadBalancer implements ReactorServiceInstanceLoadBalancer {
    private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
    private String serviceId;
    private final AtomicInteger position;
    public VersionGrayLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) {
        this(serviceInstanceListSupplierProvider, serviceId, new Random().nextInt(1000));
    }
    public VersionGrayLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId, int seedPosition) {
        this.serviceId = serviceId;
        this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
        this.position = new AtomicInteger(seedPosition);
    }
    @Override
    public Mono<Response<ServiceInstance>> choose(Request request) {
  HttpHeaders headers = ((RequestDataContext) request.getContext()).getClientRequest().getHeaders();
        ServiceInstanceListSupplier supplier = this.serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
  return supplier.get(request).next().map(serviceInstances -> processInstanceResponse(supplier, serviceInstances, headers));
    }
 private Response<ServiceInstance> processInstanceResponse(ServiceInstanceListSupplier supplier, List<ServiceInstance> serviceInstances, HttpHeaders headers) {
  if (serviceInstances.isEmpty()) {
   if (log.isWarnEnabled()) {
    log.warn("No servers available for service: " + serviceId);
   }
   return new EmptyResponse();
  } else {
   String reqVersion = headers.getFirst("VERSION");
   if (!StrUtil.isEmpty(reqVersion)) {
    List<ServiceInstance> serviceInstances2 = serviceInstances.stream()
      .filter(instance -> reqVersion.equals(instance.getMetadata().get("VERSION")))
      .collect(Collectors.toList());
    if (serviceInstances2.size() > 0) {
     serviceInstances = serviceInstances2;
    }
   }
   Response<ServiceInstance> serviceInstanceResponse = getInstanceResponse(serviceInstances);
   if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {
    ((SelectedInstanceCallback) supplier).selectedServiceInstance(serviceInstanceResponse.getServer());
   }
   return serviceInstanceResponse;
  }
 }
 private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
  int pos = Math.abs(this.position.incrementAndGet());
  ServiceInstance instance = instances.get(pos % instances.size());
  return new DefaultResponse(instance);
 }
}


GrayLoadBalancerClientConfiguration.java


获取VersionGrayLoadBalancer实例的配置类,此配置类不能在全局中注册,全局中注册会导致全局中就有一个VersionGrayLoadBalancer实例,但是这个实例并没有对应的serverId,会导致获取不到微服务实例导致报错,如果跟启动类的路径下需要啊启动类上增加扫码注解排除这个类的扫描

import com.mobk.base.common.gray.factory.GrayLoadBalancerClientFactory;
import com.mobk.base.common.gray.loadbalancer.VersionGrayLoadBalancer;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientConfiguration;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
@Configuration(proxyBeanMethods = false)
@ConditionalOnDiscoveryEnabled
public class GrayLoadBalancerClientConfiguration extends LoadBalancerClientConfiguration {
 @Bean
 public ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment, GrayLoadBalancerClientFactory grayLoadBalancerClientFactory) {
  String name = environment.getProperty(GrayLoadBalancerClientFactory.PROPERTY_NAME);
  return new VersionGrayLoadBalancer(grayLoadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
 }
}


GrayLoadBalancerClientFactory.java


这个主要参照原本的org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory


主要改的是其获取LoadBalancer实例的配置类为GrayLoadBalancerClientConfiguration,本来是想不用重写的,但是原本的LoadBalancerClientFactory是直接把这个配置类写死了,不得不重写

import com.mobk.base.common.gray.config.GrayLoadBalancerClientConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties;
import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
import org.springframework.cloud.context.named.NamedContextFactory;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientSpecification;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.core.env.Environment;
@Slf4j
public class GrayLoadBalancerClientFactory extends NamedContextFactory<LoadBalancerClientSpecification>
  implements ReactiveLoadBalancer.Factory<ServiceInstance> {
 public static final String NAMESPACE = "loadbalancer";
 public static final String PROPERTY_NAME = NAMESPACE + ".client.name";
 private final LoadBalancerClientsProperties properties;
 public GrayLoadBalancerClientFactory(LoadBalancerClientsProperties properties) {
     //主要修改的是这行代码,使用重写后的获取LoadBalancer配置类
  super(GrayLoadBalancerClientConfiguration.class, NAMESPACE, PROPERTY_NAME);
  this.properties = properties;
 }
 public static String getName(Environment environment) {
  return environment.getProperty(PROPERTY_NAME);
 }
 @Override
 public ReactiveLoadBalancer<ServiceInstance> getInstance(String serviceId) {
  return getInstance(serviceId, ReactorServiceInstanceLoadBalancer.class);
 }
 @Override
 public LoadBalancerProperties getProperties(String serviceId) {
  if (properties == null) {
   if (log.isWarnEnabled()) {
    log.warn("LoadBalancerClientsProperties is null. Please use the new constructor.");
   }
   return null;
  }
  if (serviceId == null || !properties.getClients().containsKey(serviceId)) {
   return properties;
  }
  return properties.getClients().get(serviceId);
 }
}


网关的使用

GrayReactiveLoadBalancerClientFilter.java


网关需要重写路由拦截器,并注册到spring。参考原本的org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter修改的


主要修改原本的路由方式前缀 lb->grayLb 灰度理由前缀做区分、

LoadBalancerClientFactory->GrayLoadBalancerClientFactory 修改获取LoadBalancer的工厂为重写后的

import com.mobk.base.common.gray.factory.GrayLoadBalancerClientFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.*;
import org.springframework.cloud.gateway.config.GatewayLoadBalancerProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter;
import org.springframework.cloud.gateway.support.DelegatingServiceInstance;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.*;
@Slf4j
public class GrayReactiveLoadBalancerClientFilter implements GlobalFilter, Ordered {
 /**
  * Order of filter.
  */
 public static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10150;
    //使用重写后的LoadBalancerClient工厂,获取重写后的LoadBalancer实例
 private final GrayLoadBalancerClientFactory clientFactory;
 private final GatewayLoadBalancerProperties properties;
 public GrayReactiveLoadBalancerClientFilter(GrayLoadBalancerClientFactory clientFactory, GatewayLoadBalancerProperties properties) {
  this.clientFactory = clientFactory;
  this.properties = properties;
 }
 @Override
 public int getOrder() {
  return LOAD_BALANCER_CLIENT_FILTER_ORDER;
 }
 @Override
 public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
  String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);
        //修改路由规则前缀
  if (url == null || (!"grayLb".equals(url.getScheme()) && !"grayLb".equals(schemePrefix))) {
   return chain.filter(exchange);
  }
  // preserve the original url
  addOriginalRequestUrl(exchange, url);
  if (log.isTraceEnabled()) {
   log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName() + " url before: " + url);
  }
  URI requestUri = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
  String serviceId = requestUri.getHost();
  Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator
    .getSupportedLifecycleProcessors(clientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
      RequestDataContext.class, ResponseData.class, ServiceInstance.class);
  DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest<>(
    new RequestDataContext(new RequestData(exchange.getRequest()), getHint(serviceId)));
  return choose(lbRequest, serviceId, supportedLifecycleProcessors).doOnNext(response -> {
   if (!response.hasServer()) {
    supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
      .onComplete(new CompletionContext<>(CompletionContext.Status.DISCARD, lbRequest, response)));
    throw NotFoundException.create(properties.isUse404(), "Unable to find instance for " + url.getHost());
   }
   ServiceInstance retrievedInstance = response.getServer();
   URI uri = exchange.getRequest().getURI();
   // if the `lb:<scheme>` mechanism was used, use `<scheme>` as the default,
   // if the loadbalancer doesn't provide one.
   String overrideScheme = retrievedInstance.isSecure() ? "https" : "http";
   if (schemePrefix != null) {
    overrideScheme = url.getScheme();
   }
   DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance(retrievedInstance,
     overrideScheme);
   URI requestUrl = reconstructURI(serviceInstance, uri);
   if (log.isTraceEnabled()) {
    log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
   }
   exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
   exchange.getAttributes().put(GATEWAY_LOADBALANCER_RESPONSE_ATTR, response);
   supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, response));
  }).then(chain.filter(exchange))
    .doOnError(throwable -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
      .onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
        CompletionContext.Status.FAILED, throwable, lbRequest,
        exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR)))))
    .doOnSuccess(aVoid -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
      .onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
        CompletionContext.Status.SUCCESS, lbRequest,
        exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR),
        new ResponseData(exchange.getResponse(), new RequestData(exchange.getRequest()))))));
 }
 protected URI reconstructURI(ServiceInstance serviceInstance, URI original) {
  return LoadBalancerUriTools.reconstructURI(serviceInstance, original);
 }
 private Mono<Response<ServiceInstance>> choose(Request<RequestDataContext> lbRequest, String serviceId,
               Set<LoadBalancerLifecycle> supportedLifecycleProcessors) {
  ReactorLoadBalancer<ServiceInstance> loadBalancer = this.clientFactory.getInstance(serviceId,
    ReactorServiceInstanceLoadBalancer.class);
  if (loadBalancer == null) {
   throw new NotFoundException("No loadbalancer available for " + serviceId);
  }
  supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest));
  return loadBalancer.choose(lbRequest);
 }
 private String getHint(String serviceId) {
  LoadBalancerProperties loadBalancerProperties = clientFactory.getProperties(serviceId);
  Map<String, String> hints = loadBalancerProperties.getHint();
  String defaultHint = hints.getOrDefault("default", "default");
  String hintPropertyValue = hints.get(serviceId);
  return hintPropertyValue != null ? hintPropertyValue : defaultHint;
 }
}



注册GrayLoadBalancerClientFactory和GrayReactiveLoadBalancerClientFilter

import com.mobk.base.common.gray.factory.GrayLoadBalancerClientFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientSpecification;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.util.Collections;
import java.util.List;
@Configuration(proxyBeanMethods = false)
public class GrayLoadBalancerAutoConfiguration {
 private final ObjectProvider<List<LoadBalancerClientSpecification>> configurations;
 public GrayLoadBalancerAutoConfiguration(ObjectProvider<List<LoadBalancerClientSpecification>> configurations) {
  this.configurations = configurations;
 }
    /**
     * 注册GrayLoadBalancerClientFactory并用@Primary标记为主要的
     */
 @Bean
 @Primary
 public GrayLoadBalancerClientFactory grayLoadBalancerClientFactory(LoadBalancerClientsProperties properties) {
  GrayLoadBalancerClientFactory clientFactory = new GrayLoadBalancerClientFactory(properties);
  clientFactory.setConfigurations(this.configurations.getIfAvailable(Collections::emptyList));
  return clientFactory;
 }
    /**
     * 注册拦截器
     */
 @Bean
 public GlobalFilter grayReactiveLoadBalancerClientFilter(GrayLoadBalancerClientFactory clientFactory, GatewayLoadBalancerProperties properties) {
  return new GrayReactiveLoadBalancerClientFilter(clientFactory, properties);
 }
}



修改网关配置,增加灰度路由配置


spring:

 cloud:

   gateway:

     routes:

       - id: admin-gray

         #使用灰度路由前缀

         uri: grayLb://admin

         predicates:

           - Path=/gray/**

修改微服务配置,增加metadata数据,或者可以去nacos修改微服务的metadata数据,不过重启服务后可能会失效

# 服务配置文件

spring:

 cloud:

   nacos:

     discovery:

       metadata:

         VERSION: v2

最后调用接口增加请求头 VERSION:v2即可请求到指定的服务


feign使用

注册GrayLoadBalancerClientFactory

重新注册BlockingLoadBalancerClient,使用GrayLoadBalancerClientFactory替换原来的LoadBalancerClientFactory

import com.mobk.base.common.gray.factory.GrayLoadBalancerClientFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientSpecification;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.util.Collections;
import java.util.List;
@Configuration(proxyBeanMethods = false)
public class GrayLoadBalancerAutoConfiguration {
 private final ObjectProvider<List<LoadBalancerClientSpecification>> configurations;
 public GrayLoadBalancerAutoConfiguration(ObjectProvider<List<LoadBalancerClientSpecification>> configurations) {
  this.configurations = configurations;
 }
    /**
     * 注册GrayLoadBalancerClientFactory并用@Primary标记为主要的
     */
 @Bean
 @Primary
 public GrayLoadBalancerClientFactory grayLoadBalancerClientFactory(LoadBalancerClientsProperties properties) {
  GrayLoadBalancerClientFactory clientFactory = new GrayLoadBalancerClientFactory(properties);
  clientFactory.setConfigurations(this.configurations.getIfAvailable(Collections::emptyList));
  return clientFactory;
 }
    /**
     * 注册BlockingLoadBalancerClient,注入重写后的GrayLoadBalancerClientFactory
     */
    @Bean
 public LoadBalancerClient blockingLoadBalancerClient(GrayLoadBalancerClientFactory loadBalancerClientFactory) {
  return new BlockingLoadBalancerClient(loadBalancerClientFactory);
 }
}



在feign接口的


方法上的RequestMapping注解添加headers={"VERSION=v2"}

@PostMapping(value = "/log",headers = {"VERSION=v2"})

去微服务提供者修改配置添加metadata数据VERSION:v2

# 服务配置文件

spring:

 cloud:

   nacos:

     discovery:

       metadata:

         VERSION: v2

直接调用feign接口即可


将以上所有配置和类提取到统一模块下进行配置

分拆上面的两个GrayLoadBalancerAutoConfiguration类为3个


GrayLoadBalancerAutoConfiguration.java 这个只注册工厂类

package com.mobk.base.common.gray.config;
import com.mobk.base.common.gray.factory.GrayLoadBalancerClientFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientSpecification;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import java.util.Collections;
import java.util.List;
@Configuration(proxyBeanMethods = false)
public class GrayLoadBalancerAutoConfiguration {
 private final ObjectProvider<List<LoadBalancerClientSpecification>> configurations;
 public GrayLoadBalancerAutoConfiguration(ObjectProvider<List<LoadBalancerClientSpecification>> configurations) {
  this.configurations = configurations;
 }
 @Bean
 @Primary
 public GrayLoadBalancerClientFactory grayLoadBalancerClientFactory(LoadBalancerClientsProperties properties) {
  GrayLoadBalancerClientFactory clientFactory = new GrayLoadBalancerClientFactory(properties);
  clientFactory.setConfigurations(this.configurations.getIfAvailable(Collections::emptyList));
  return clientFactory;
 }
}


GrayLoadBalancerAutoConfigurationFeign.java


对Feign的单独配置类,只在Feign环境下启用

package com.mobk.base.common.gray.config;
import com.mobk.base.common.gray.factory.GrayLoadBalancerClientFactory;
import feign.Feign;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Feign.class)
public class GrayLoadBalancerAutoConfigurationFeign {
 /**
  * 在feign环境下启用
  * @param loadBalancerClientFactory
  * @return
  */
 @Bean
 public LoadBalancerClient blockingLoadBalancerClient(GrayLoadBalancerClientFactory loadBalancerClientFactory) {
  return new BlockingLoadBalancerClient(loadBalancerClientFactory);
 }
}


GrayLoadBalancerAutoConfigurationGateway.java


对Gateway的单独配置类,只在网关环境下启动

package com.mobk.base.common.gray.config;
import com.mobk.base.common.gray.factory.GrayLoadBalancerClientFactory;
import com.mobk.base.common.gray.filter.GrayReactiveLoadBalancerClientFilter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.cloud.gateway.config.GatewayAutoConfiguration;
import org.springframework.cloud.gateway.config.GatewayLoadBalancerProperties;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ConditionalOnBean(GatewayAutoConfiguration.class)
@Configuration(proxyBeanMethods = false)
public class GrayLoadBalancerAutoConfigurationGateway {
  /**
   * 在gateway环境下启用
   * @param clientFactory
   * @param properties
   * @return
   */
  @Bean
  public GlobalFilter grayReactiveLoadBalancerClientFilter(GrayLoadBalancerClientFactory clientFactory, GatewayLoadBalancerProperties properties) {
    return new GrayReactiveLoadBalancerClientFilter(clientFactory, properties);
  }
}


将几个配置加入到自动配置中

spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=

com.mobk.base.common.gray.config.GrayLoadBalancerAutoConfiguration,

com.mobk.base.common.gray.config.GrayLoadBalancerAutoConfigurationFeign,

com.mobk.base.common.gray.config.GrayLoadBalancerAutoConfigurationGateway

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
1月前
|
负载均衡 Java API
【Spring Cloud生态】Spring Cloud Gateway基本配置
【Spring Cloud生态】Spring Cloud Gateway基本配置
35 0
|
3月前
|
Java Spring
【Azure Spring Cloud】Spring Cloud Azure 4.0 调用Key Vault遇见认证错误 AADSTS90002: Tenant not found.
【Azure Spring Cloud】Spring Cloud Azure 4.0 调用Key Vault遇见认证错误 AADSTS90002: Tenant not found.
|
4月前
|
负载均衡 Java Spring
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
473 15
|
3月前
|
Java Spring 容器
【Azure Spring Cloud】在Azure Spring Apps上看见 App Memory Usage 和 jvm.menory.use 的指标的疑问及OOM
【Azure Spring Cloud】在Azure Spring Apps上看见 App Memory Usage 和 jvm.menory.use 的指标的疑问及OOM
|
3月前
|
存储 Java Spring
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
|
3月前
|
SQL Java 数据库连接
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
|
3月前
|
Java 开发工具 Spring
【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known
【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known
|
3月前
|
NoSQL Java Redis
【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常
【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常
|
3月前
|
Java Spring
【Azure 应用服务】记一次Azure Spring Cloud 的部署错误 (az spring-cloud app deploy -g dev -s testdemo -n demo -p ./hellospring-0.0.1-SNAPSHOT.jar --->>> Failed to wait for deployment instances to be ready)
【Azure 应用服务】记一次Azure Spring Cloud 的部署错误 (az spring-cloud app deploy -g dev -s testdemo -n demo -p ./hellospring-0.0.1-SNAPSHOT.jar --->>> Failed to wait for deployment instances to be ready)
|
3月前
|
Java Maven Python
【Azure Spring Cloud】部署Azure spring cloud 失败
【Azure Spring Cloud】部署Azure spring cloud 失败