网关 Spring Cloud Gateway 实战负载均衡(Spring Cloud Loadbalancer)

💨 作者:laker,因为喜欢LOL滴神faker,又是NBA湖人队🏀(laker)粉丝儿(主要是老詹的粉丝儿),本人又姓,故取笔名:laker
❤️喜欢分享自己工作中遇到的问题和解决方案以及一些读书笔记和心得分享
🌰本人创建了微信公众号【Java大厂面试官】,用于和大家交流分享
🏰 个人微信【lakernote】,加作者备注下暗号:cv之道


本文Spring Cloud Gateway 版本:2020.0.0

Spring Boot版本:2.4.1

前言

拿着最新版本来实战一波负载均衡,毕竟之前都是demo级别的玩具车,但是遇到坑了,
官网说用lb://lakerservice形式即可,但是配置完成后,并未生效。

spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**

这个官网没有详细说明,查资料也没有,排查结果如下:

必须加入依赖

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

在这里插入图片描述

Spring Cloud Ribbon 高版本移除了
在这里插入图片描述

看到这儿,我靠,大呼 ribbon凉了啊

原理参考类

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ ReactiveLoadBalancer.class, LoadBalancerAutoConfiguration.class, DispatcherHandler.class })
@AutoConfigureAfter(LoadBalancerAutoConfiguration.class)
@EnableConfigurationProperties(GatewayLoadBalancerProperties.class)
public class GatewayReactiveLoadBalancerClientAutoConfiguration {
	@Bean
	@ConditionalOnBean(LoadBalancerClientFactory.class)
	@ConditionalOnMissingBean(ReactiveLoadBalancerClientFilter.class)
	@ConditionalOnEnabledGlobalFilter
	public ReactiveLoadBalancerClientFilter gatewayLoadBalancerClientFilter(LoadBalancerClientFactory clientFactory,
			GatewayLoadBalancerProperties properties, LoadBalancerProperties loadBalancerProperties) {
		return new ReactiveLoadBalancerClientFilter(clientFactory, properties, loadBalancerProperties);
	}
}

#websocket负载均衡
- id: websocket_route
# lb代表服务名,
# 这里负载所有的websocket
uri: lb:ws://xx-ws
predicates:
- Path=/websocket/**

Spring Cloud Loadbalancer

Spring Cloud提供了自己的客户端负载均衡器抽象和实现。对于负载平衡机制,ReactiveLoadBalancer已添加了接口,并为其提供了基于Round-RobinRandom的实现。为了获得实例以从反应式中进行选择ServiceInstanceListSupplier 。当前,我们支持基于服务发现的实现,ServiceInstanceListSupplier 该实现使用类路径中可用的发现客户端从服务发现中检索可用实例。

我靠难道说,只支持服务发现的方式了吗,没有静态配置的负载均衡了???

找了一大圈,还好找到了

0. SimpleDiscoveryClient

可以结合注册中心使用,也可以静态配置

传送门

如果DiscoveryClient类路径中没有支持服务注册表的SimpleDiscoveryClient 实例,则将使用实例,该实例使用属性来获取有关服务和实例的信息。

有关可用实例的信息应通过以下格式的属性传递给属性: spring.cloud.discovery.client.simple.instances.service1[0].uri=http://s11:8080,其中 spring.cloud.discovery.client.simple.instances是公共前缀,然后service1代表所讨论服务的ID,而[0]表示实例的索引号(如示例中所示,索引以0)开头,然后的值uri是实例可用的实际URI。

spring:
  cloud:
    gateway:
      routes:
        - id: lb_laker
          uri: lb://lakerservices
          predicates:
            - Path=/get
    discovery:
      client:
        simple:
          instances:
            lakerservices:
              - uri: http://httpbin.org
              - uri: https://httpbin.org
management:
  endpoints:
    web:
      exposure:
        include: "*"

1. 在负载均衡算法之间切换

ReactiveLoadBalancer默认情况下使用的实现是RoundRobinLoadBalancer。要针对选定的服务或所有服务切换到不同的实现,可以使用自定义LoadBalancer配置机制

例如,可以通过@LoadBalancerClient注释传递以下配置以切换为使用RandomLoadBalancer

public class CustomLoadBalancerConfiguration {

    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
            LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RandomLoadBalancer(loadBalancerClientFactory
                .getLazyProvider(name, ServiceInstanceListSupplier.class),
                name);
    }
}

2. 实例健康检查

传送门

可以为LoadBalancer启用计划健康检查。为此提供了HealthCheckServiceInstanceListSupplier。它定期验证委托ServiceInstanceListSupplier提供的实例是否仍然存在,并且只返回健康的实例,除非没有实例—然后返回所有检索到的实例。

在使用SimpleDiscoveryClient时,这种机制特别有用。对于由实际服务注册中心支持的客户端,不需要使用它,因为我们在查询外部ServiceDiscovery之后已经获得了健康的实例。

对于每个服务只有少量实例的设置,也建议使用此供应商,以避免重试调用失败的实例。

问题

这里也是踩了蛮多的坑
Spring Cloud Loadbalancer
先上能用的配置,无需增加类。

spring:
  cloud:
    gateway:
      routes:
        - id: lb_laker
          uri: lb://lakerservices
          predicates:
            - Path=/**
      httpserver:
        wiretap: true
      httpclient:
        wiretap: true
    discovery:
      client:
        simple:
          instances:
            lakerservices:  # 一定要带端口
              - uri: http://httpbin.org:80
              - uri: https://httpbin.org:443
    loadbalancer:
      health-check:
        path:
          lakerservices: /get
        initial-delay: 0 #运行状况检查计划程序的初始延迟值。
        interval: 5s # 重新运行运行状况检查计划程序的时间间隔。
      configurations: health-check #启用预定义的负载平衡器配置。
management:
  endpoints:
    web:
      exposure:
        include: "*"
logging:
  level:
    org.springframework.cloud.gateway: trace
    org.springframework.cloud.loadbalancer: trace
    org.springframework.web.reactive: trace



问题1:健康检查生效问题

可以参考这个类:LoadBalancerClientConfiguration
在这里插入图片描述
1.使用配置文件让其生效【推荐

spring:
  cloud:
    loadbalancer:
      configurations: health-check #启用预定义的负载平衡器配置。

2.代码模式,必须指定name为service-id,且只对这个service-id生效

@Configuration
@LoadBalancerClient(name = "lakerservices", configuration = CustomLoadBalancerConfiguration.class)
public class CustomLoadBalancerConfiguration {

    @Bean
    public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
            ConfigurableApplicationContext context) {
        return ServiceInstanceListSupplier.builder()
                .withDiscoveryClient()
                .withHealthChecks()
                .build(context);
    }
}
问题2:实例健康检查配置

指定检查的path,默认的是/actuator/health
只要返回的Status=200即可。
配置方式如下
serviceid1:/path

    path:
          serviceid1:/path
          serviceid2:/path
spring:
    loadbalancer:
      health-check:
        path:
          lakerservices: /get
        initial-delay: 0 #运行状况检查计划程序的初始延迟值。
        interval: 5s # 重新运行运行状况检查计划程序的时间间隔。

源码跟踪

ReactiveLoadBalancerClientFilter.filter

- ReactiveLoadBalancerClientFilter.choose

- RoundRobinLoadBalancer.choose

- HealthCheckServiceInstanceListSupplier

问题3:实例路径配置问题

因为想简单的使用静态的配置,没加健康检查的时候

     - uri: http://httpbin.org
     - uri: https://httpbin.org

这样是没问题的,可以正常访问,但是如果加了健康检查就拉了,必须加上端口才可以,如下:

spring:
  cloud:
    gateway:
      routes:
        - id: lb_laker
          uri: lb://lakerservices
          predicates:
            - Path=/**
    discovery:
      client:
        simple:
          instances:
            lakerservices:  # 一定要带端口
              - uri: http://httpbin.org:80
              - uri: https://httpbin.org:443

Spring Cloud 相关系列文章目录

网关服务

Spring Cloud Gateway


QQ群【837324215】
关注我的公众号【Java大厂面试官】,回复:常用工具资源等关键词(更多关键词,关注后注意提示信息)获取更多免费资料。

公众号也会持续输出高质量文章,和大家共同进步。

Spring Cloud GatewaySpring Cloud生态中的一个API网关框架,可以实现请求的路由、限流、鉴权、监控等功能。其中,负载均衡Spring Cloud Gateway中非常重要的功能之一。本篇文章就来介绍一下Spring Cloud Gateway负载均衡功能。 在Spring Cloud Gateway中,负载均衡是通过路由(Route)来实现的。每一个路由对应一个或多个服务实例,Spring Cloud Gateway会根据负载均衡策略,将请求转发到对应的服务实例。 Spring Cloud Gateway支持多种负载均衡策略,包括: 1. RoundRobinLoadBalancer:轮询负载均衡策略,每个服务实例轮流接收请求。 2. WeightedResponseTimeLoadBalancer:响应时间加权负载均衡策略,对每个服务实例的响应时间进行加权,响应时间短的服务实例接收更多的请求。 3. ZoneAvoidanceRule:区域避让负载均衡策略,对于不同区域的服务实例,Spring Cloud Gateway会尽量选择同一区域的服务实例来处理请求。 除了以上几种负载均衡策略之外,Spring Cloud Gateway还支持自定义负载均衡策略。在自定义负载均衡策略时,需要实现Spring Cloud GatewayLoadBalancerClient接口和LoadBalancer接口。 下面是一个示例,展示了如何在Spring Cloud Gateway中使用RoundRobinLoadBalancer策略: ```java @Configuration public class GatewayConfig { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route(r -> r.path("/foo/**") .uri("lb://service-foo") .id("service-foo") .lb(new RoundRobinLoadBalancer())) .build(); } } ``` 在上面的示例中,我们配置了一个路由,将请求转发到service-foo服务实例。并且指定了负载均衡策略为RoundRobinLoadBalancer。 除了在配置文件中配置负载均衡策略之外,Spring Cloud Gateway还支持通过请求头、请求参数等方式,动态设置负载均衡策略。这样可以在运行时根据实际情况,动态调整负载均衡策略。 总的来说,Spring Cloud Gateway负载均衡功能非常强大,支持多种负载均衡策略,并且支持自定义负载均衡策略。这为我们构建高可用、高性能的分布式系统提供了很大的便利。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lakernote

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值