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/**

公共属性配置

两种负载均衡都引入了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<String, String> path = new LinkedCaseInsensitiveMap();

        ...省略...
    }
}

一、基于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);
    }
}

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

引入依赖

<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

使用默认的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

其他的ribbon的配置项如下

<clientName>.ribbon.NFLoadBalancerClassName: ILoadBalancer
<clientName>.ribbon.NFLoadBalancerRuleClassName: IRule
<clientName>.ribbon.NFLoadBalancerPingClassName: IPing
<clientName>.ribbon.NIWSServerListClassName: ServerList
<clientName>.ribbon.NIWSServerListFilterClassName: ServerListFilter

二、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() {
            }
        }
    }
}
  •  该自动配置类在LoadBalancerAutoConfiguration自动配置类之后执行,该配置类在spring-cloud-commons中
  • 该自动配置类在GatewayLoadBalancerClientAutoConfiguration自动配置类之前执行,也就是前面的基于Ribbon的自动装配类,由此可见,gateway是优先使用ReactiveLoadBalancer的,只有没有开启ReactiveLoadBalancer时才使用使用Ribbon

引入依赖

<!-- 引入spring-cloud-loadbalancer -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

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

注意:如果在项目的类路径下存在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

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<ServiceInstance> getInstances(String serviceId) {
        List<ServiceInstance> serviceInstances = new ArrayList();
        List<DefaultServiceInstance> serviceInstanceForService = (List)this.simpleDiscoveryProperties.getInstances().get(serviceId);
        if (serviceInstanceForService != null) {
            serviceInstances.addAll(serviceInstanceForService);
        }

        return serviceInstances;
    }

    public List<String> getServices() {
        return new ArrayList(this.simpleDiscoveryProperties.getInstances().keySet());
    }

    public int getOrder() {
        return this.simpleDiscoveryProperties.getOrder();
    }
}

SimpleDiscoveryProperties  服务实例的属性配置

@ConfigurationProperties(
    prefix = "spring.cloud.discovery.client.simple"
)
public class SimpleDiscoveryProperties {
    //在配置文件中配置的实例属性
    private Map<String, List<DefaultServiceInstance>> instances = new HashMap();
    private DefaultServiceInstance local = new DefaultServiceInstance((String)null, (String)null, (String)null, 0, false);
    private int order = 0;
}

DefaultServiceInstance默认的服务实例定义

public class DefaultServiceInstance implements ServiceInstance {
    private String instanceId;
    private String serviceId;
    private String host;
    private int port;
    private boolean secure;
    private Map<String, String> metadata;
    private URI uri;
    ...省略...
}

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

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐