SpringCloud灰度路由

简介: 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

相关实践学习
部署高可用架构
本场景主要介绍如何使用云服务器ECS、负载均衡SLB、云数据库RDS和数据传输服务产品来部署多可用区高可用架构。
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
1月前
|
消息中间件 NoSQL Java
Spring Cloud项目实战Spring Cloud视频教程 含源码
Spring Cloud项目实战Spring Cloud视频教程 含源码
43 1
|
1月前
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(二)Rest微服务工程搭建
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(二)Rest微服务工程搭建
78 0
|
1月前
|
消息中间件 Cloud Native Java
【Spring云原生系列】SpringBoot+Spring Cloud Stream:消息驱动架构(MDA)解析,实现异步处理与解耦合
【Spring云原生系列】SpringBoot+Spring Cloud Stream:消息驱动架构(MDA)解析,实现异步处理与解耦合
|
1月前
|
SpringCloudAlibaba Java 持续交付
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
273 0
|
1月前
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
172 0
|
1月前
|
消息中间件 JSON Java
Spring Boot、Spring Cloud与Spring Cloud Alibaba版本对应关系
Spring Boot、Spring Cloud与Spring Cloud Alibaba版本对应关系
2517 0
|
1月前
|
负载均衡 Java 开发者
【SpringCloud】什么是Spring Cloud----综述
【SpringCloud】什么是Spring Cloud----综述
21 0
|
1月前
|
Java Nacos 开发者
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
|
1月前
|
开发框架 负载均衡 Java
Spring boot与Spring cloud之间的关系
总之,Spring Boot和Spring Cloud之间的关系是一种构建和扩展的关系,Spring Boot提供了基础,而Spring Cloud在此基础上提供了分布式系统和微服务架构所需的扩展和工具。
30 4
Spring boot与Spring cloud之间的关系
|
1月前
|
Cloud Native Dubbo Java
如何确定微服务项目中Spring Boot、Spring Cloud、Spring Cloud Alibaba三者之间的版本
如何确定微服务项目中Spring Boot、Spring Cloud、Spring Cloud Alibaba三者之间的版本
57 0