• Spring Cloud Gateway网关两种负载均衡


    Gateway有两种客户端负载均衡器,LoadBalancerClientFilter和ReactiveLoadBalancerClientFilter。

    LoadBalancerClientFilter使用一个Ribbon的阻塞式LoadBalancerClient,Gateway建议使用ReactiveLoadBalancerClientFilter,

    可以通过设置spring.cloud.loadbalancer.ribbon.enabled=false,切换到ReactiveLoadBalancerClientFilter

    无论使用Ribbon还是LoadBalancer,在Route中配置的lb是一样的,如下:

    serviceId为providerService

    #=======================路由配置RouteDefinition=======================
    #id:路由标识,具有唯一性
    spring.cloud.gateway.routes[0].id=provider-http
    #url:目标服务地址,请求转发后的地址,lb:协议表示开启负载均衡
    #uri: lb://renren-api
    spring.cloud.gateway.routes[0].uri=lb://providerService
    #predicates:断言/路由条件,匹配 HTTP请求内容
    #转发地址格式: uri/nacos/provider/**
    spring.cloud.gateway.routes[0].predicates[0]=Path=/provider-http/**
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    公共属性配置

    两种负载均衡都引入了LoadBalancerProperties健康检查类

    @ConfigurationProperties("spring.cloud.loadbalancer")
    public class LoadBalancerProperties {
        private LoadBalancerProperties.HealthCheck healthCheck = new LoadBalancerProperties.HealthCheck();
    
        ...省略...
    
        public static class HealthCheck {
            private int initialDelay = 0;
            private Duration interval = Duration.ofSeconds(25L);
            private Map path = new LinkedCaseInsensitiveMap();
    
            ...省略...
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    一、基于Ribbon的LoadBalancerClientFilter

    gateway中的自动配置类GatewayLoadBalancerClientAutoConfiguration

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({LoadBalancerClient.class, RibbonAutoConfiguration.class, DispatcherHandler.class})
    @AutoConfigureAfter({RibbonAutoConfiguration.class})
    @EnableConfigurationProperties({LoadBalancerProperties.class})
    public class GatewayLoadBalancerClientAutoConfiguration {
        public GatewayLoadBalancerClientAutoConfiguration() {
        }
    
        @Bean
        @ConditionalOnBean({LoadBalancerClient.class})
        //缺失LoadBalancerClientFilter和ReactiveLoadBalancerClientFilter的条件下,就new LoadBalancerClientFilter
        //也就是说,默认情况下是使用LoadBalancerClientFilter的
        @ConditionalOnMissingBean({LoadBalancerClientFilter.class, ReactiveLoadBalancerClientFilter.class})
        @ConditionalOnEnabledGlobalFilter
        public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client, LoadBalancerProperties properties) {
            return new LoadBalancerClientFilter(client, properties);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    该自动配置类需要在RibbonAutoConfiguration自动配置类之后执行,该类是spring-cloud-netflix-ribbon的自动配置类,因此需要引入下面的jar包依赖

    引入依赖

    
         org.springframework.cloud
         spring-cloud-starter-netflix-ribbon
    
    
    • 1
    • 2
    • 3
    • 4

    使用默认的ribbon,则ribbon的配置如下

    #=======================ribbon配置(使用netflix的Ribbon负载均衡)=======================
    #关闭nacos集成ribbon,否则ribbon客户端会从nacos注册中心获取服务列表
    ribbon.nacos.enabled=false
    #配置serviceId为providerService的服务List
    providerService.ribbon.listOfServers=http://192.168.10.1:8080,http://192.168.10.2:8080
    #配置serviceId为providerService的服务负载均衡
    #providerService.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
    providerService.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.AvailabilityFilteringRule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    其他的ribbon的配置项如下

    .ribbon.NFLoadBalancerClassName: ILoadBalancer
    .ribbon.NFLoadBalancerRuleClassName: IRule
    .ribbon.NFLoadBalancerPingClassName: IPing
    .ribbon.NIWSServerListClassName: ServerList
    .ribbon.NIWSServerListFilterClassName: ServerListFilter
    
    • 1
    • 2
    • 3
    • 4
    • 5

    二、Spring Cloud Loadbalancer

    Spring Cloud Load Balancer并不是一个独立的项目,而是spring-cloud-commons其中的一个模块,因此很多配置和类可以在spring-cloud-common中找到。

    官网文档地址

    spring-cloud-loadbalancer

    gateway中的自动配置类GatewayReactiveLoadBalancerClientAutoConfiguration

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({LoadBalancerClient.class, ReactiveLoadBalancer.class, LoadBalancerAutoConfiguration.class, DispatcherHandler.class})
    @AutoConfigureBefore({GatewayLoadBalancerClientAutoConfiguration.class})
    @AutoConfigureAfter({LoadBalancerAutoConfiguration.class})
    @EnableConfigurationProperties({LoadBalancerProperties.class})
    public class GatewayReactiveLoadBalancerClientAutoConfiguration {
        public GatewayReactiveLoadBalancerClientAutoConfiguration() {
        }
    
        @Bean
        @ConditionalOnBean({LoadBalancerClientFactory.class})
        @ConditionalOnMissingBean({ReactiveLoadBalancerClientFilter.class})
      //这个条件很重要
        @Conditional({GatewayReactiveLoadBalancerClientAutoConfiguration.OnNoRibbonDefaultCondition.class})
        @ConditionalOnEnabledGlobalFilter
        public ReactiveLoadBalancerClientFilter gatewayLoadBalancerClientFilter(LoadBalancerClientFactory clientFactory, LoadBalancerProperties properties) {
            return new ReactiveLoadBalancerClientFilter(clientFactory, properties);
        }
    
        private static final class OnNoRibbonDefaultCondition extends AnyNestedCondition {
            private OnNoRibbonDefaultCondition() {
                super(ConfigurationPhase.REGISTER_BEAN);
            }
    
            @ConditionalOnMissingClass({"org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient"})
            static class RibbonLoadBalancerNotPresent {
                RibbonLoadBalancerNotPresent() {
                }
            }
            //spring.cloud.loadbalancer.ribbon.enabled=false,才会使用ReactiveLoadBalancerClientFilter
            @ConditionalOnProperty(
                value = {"spring.cloud.loadbalancer.ribbon.enabled"},
                havingValue = "false"
            )
            static class RibbonNotEnabled {
                RibbonNotEnabled() {
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 该自动配置类在LoadBalancerAutoConfiguration自动配置类之后执行,该配置类在spring-cloud-commons中
    • 该自动配置类在GatewayLoadBalancerClientAutoConfiguration自动配置类之前执行,也就是前面的基于Ribbon的自动装配类,由此可见,gateway是优先使用ReactiveLoadBalancer的,只有没有开启ReactiveLoadBalancer时才使用使用Ribbon

    引入依赖

    
    
        org.springframework.cloud
        spring-cloud-starter-loadbalancer
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    配置如下(从配置文件中读取服务,而不是从服务注册中心自动发现服务)

    注意:如果在项目的类路径下存在Spring Cloud Ribbon相关的类,需要通过配置关闭Ribbon功能,因为Spring Cloud默认优先使用Ribbon,因此spring.cloud.loadbalancer.ribbon.enabled禁用调Ribbon,这也是上面刚提到过的

    #=======================SpringCloudLoadBalancer配置服务列表=======================
    #使用ReactiveLoadBalancerClient时通过该参数禁用调ribbon
    spring.cloud.loadbalancer.ribbon.enabled=false
    #配置providerService的instances,不是从注册中心自动发现服务实例
    spring.cloud.discovery.client.simple.instances.providerService[0].uri=http://192.168.10.1:8080
    spring.cloud.discovery.client.simple.instances.providerService[1].uri=http://192.168.10.2:8080
    #指定健康检查请求路径,默认健康检查路径是/actuator/health
    spring.cloud.loadbalancer.health-check.path.providerService=/custom/customHealthCheckPath
    #运行状况检查计划程序的初始延迟值
    spring.cloud.loadbalancer.health-check.initial-delay=0
    #重新运行运行状况检查计划程序的时间间隔
    spring.cloud.loadbalancer.health-check.interval=5s
    #启用预定义的负载平衡器配置
    spring.cloud.loadbalancer.configurations=health-check
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    SimpleDiscoveryClient

    网关参考文档simplediscoveryclient

    如果在类路径中没有支持从注册中心发现服务的DiscoveryClient实例,则将使用SimpleDiscoveryClient实例,该实例使用SimpleDiscoveryProperties来获取有关服务和实例的信息。参考上面的配置文件中的配置

    public class SimpleDiscoveryClient implements DiscoveryClient {
        private SimpleDiscoveryProperties simpleDiscoveryProperties;
    
        public SimpleDiscoveryClient(SimpleDiscoveryProperties simpleDiscoveryProperties) {
            this.simpleDiscoveryProperties = simpleDiscoveryProperties;
        }
    
        public String description() {
            return "Simple Discovery Client";
        }
    
        public List getInstances(String serviceId) {
            List serviceInstances = new ArrayList();
            List serviceInstanceForService = (List)this.simpleDiscoveryProperties.getInstances().get(serviceId);
            if (serviceInstanceForService != null) {
                serviceInstances.addAll(serviceInstanceForService);
            }
    
            return serviceInstances;
        }
    
        public List getServices() {
            return new ArrayList(this.simpleDiscoveryProperties.getInstances().keySet());
        }
    
        public int getOrder() {
            return this.simpleDiscoveryProperties.getOrder();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    SimpleDiscoveryProperties 服务实例的属性配置

    @ConfigurationProperties(
        prefix = "spring.cloud.discovery.client.simple"
    )
    public class SimpleDiscoveryProperties {
        //在配置文件中配置的实例属性
        private Map> instances = new HashMap();
        private DefaultServiceInstance local = new DefaultServiceInstance((String)null, (String)null, (String)null, 0, false);
        private int order = 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    DefaultServiceInstance默认的服务实例定义

    public class DefaultServiceInstance implements ServiceInstance {
        private String instanceId;
        private String serviceId;
        private String host;
        private int port;
        private boolean secure;
        private Map metadata;
        private URI uri;
        ...省略...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    参考https://blog.csdn.net/abu935009066/article/details/112296435

  • 相关阅读:
    开源代码分享(3)—微电网鲁棒定价策略(附matlab代码)
    LayaBox---多状态---时间轴动画
    React router6--路由表多级路由嵌套的默认子路由问题
    嘉一机电告诉你胶球清洗装置好不好用(附安装示意图)
    “GT/Serdes/高速收发器”相关的FPGA调研
    wPDF v5支持并改进旋转文本的逻辑
    Explainable-ZSL
    mysql InnooDb存储引擎的体系结构和逻辑存储结构
    java.lang.unsupportedClassVersionError
    【英语语法】 either or / neither nor
  • 原文地址:https://blog.csdn.net/m0_67402235/article/details/126496873