SpringCloud灰度路由

本文涉及的产品
网络型负载均衡 NLB,每月750个小时 15LCU
应用型负载均衡 ALB,每月750个小时 15LCU
传统型负载均衡 CLB,每月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

相关实践学习
小试牛刀,一键部署电商商城
SAE 仅需一键,极速部署一个微服务电商商城,体验 Serverless 带给您的全托管体验,一起来部署吧!
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
目录
打赏
0
1
0
1
435
分享
相关文章
Spring Cloud Alibaba与Spring Cloud区别和联系?
Spring Cloud Alibaba与Spring Cloud区别和联系?
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
本文介绍了如何使用Spring Cloud Alibaba 2023.0.0.0技术栈构建微服务网关,以应对微服务架构中流量治理与安全管控的复杂性。通过一个包含鉴权服务、文件服务和主服务的项目,详细讲解了网关的整合与功能开发。首先,通过统一路由配置,将所有请求集中到网关进行管理;其次,实现了限流防刷功能,防止恶意刷接口;最后,添加了登录鉴权机制,确保用户身份验证。整个过程结合Nacos注册中心,确保服务注册与配置管理的高效性。通过这些实践,帮助开发者更好地理解和应用微服务网关。
463 0
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
AI 时代:从 Spring Cloud Alibaba 到 Spring AI Alibaba
本次分享由阿里云智能集团云原生微服务技术负责人李艳林主讲,主题为“AI时代:从Spring Cloud Alibaba到Spring AI Alibaba”。内容涵盖应用架构演进、AI agent框架发展趋势及Spring AI Alibaba的重磅发布。分享介绍了AI原生架构与传统架构的融合,强调了API优先、事件驱动和AI运维的重要性。同时,详细解析了Spring AI Alibaba的三层抽象设计,包括模型支持、工作流智能体编排及生产可用性构建能力,确保安全合规、高效部署与可观测性。最后,结合实际案例展示了如何利用私域数据优化AI应用,提升业务价值。
549 4
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
406 5
【Spring Cloud生态】Spring Cloud Gateway基本配置
【Spring Cloud生态】Spring Cloud Gateway基本配置
170 0
|
11月前
|
【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.
216 1
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
1294 15
【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
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问