zoukankan      html  css  js  c++  java
  • spring-cloud-gateway限流

    概述

    限流:网关上有大量请求,对指定服务进行限流,可以很大程度上提高服务的可用性与稳定性,限流的目的是通过对并发访问/请求进行限速,或对一个时间窗口内的请求进行限速来保护系统。一旦达到限制速率则可以拒绝服务、排队或等待、降级。

    在 Spring Cloud Gateway 中,有 Filter过滤器,因此可以在 pre 类型的 Filter 中自行实现上述三种过滤器。但是限流作为网关最基本的功能,Spring Cloud Gateway 官方就提供了 RequestRateLimiterGatewayFilterFactory 这个类,适用在 Redis 内的通过执行 Lua 脚本实现了令牌桶的方式。具体实现逻辑在 RequestRateLimiterGatewayFilterFactory 类中,lua 脚本在如下图所示的文件夹中:

    限流配置

    应一小伙伴要求, 将 demo 升级到了最新版本

    • spring-cloud-dependencies: Hoxton.SR3
    • spring-boot-dependencies: 2.2.6.RELEASE

    代码放置在 github.

    1. 修改配置文件
    server:
      port: 2000
    spring:
      application:
        name: idc-gateway2
      redis:
        host: localhost
        port: 6379
        timeout: 6000ms  # 连接超时时长(毫秒)
        jedis:
          pool:
            max-active: 1000  # 连接池最大连接数(使用负值表示没有限制)
            max-wait: -1ms      # 连接池最大阻塞等待时间(使用负值表示没有限制)
            max-idle: 10      # 连接池中的最大空闲连接
            min-idle: 5       # 连接池中的最小空闲连接
      cloud:
        consul:
          host: localhost
          port: 8500
        gateway:
          discovery:
            locator:
              enabled: true # gateway可以通过开启以下配置来打开根据服务的serviceId来匹配路由,默认是大写
          routes:
            - id: provider1
              uri: lb://idc-provider1
              predicates:
                - Path=/p1/**
              filters:
                - StripPrefix=1
                - name: RequestRateLimiter
                  args:
                    key-resolver: '#{@ipKeyResolver}'
                    redis-rate-limiter.replenishRate: 1
                    redis-rate-limiter.burstCapacity: 3
            - id: provider2
              uri: lb://idc-provider2
              predicates:
                - Path=/p2/**
              filters:
                - StripPrefix=1
    

    在上面的配置文件,指定程序的端口为 2000,配置了 redis 的信息,并配置了 RequestRateLimiter 的限流过滤器,该过滤器需要配置三个参数:

    • burstCapacity,令牌桶总容量。
    • replenishRate,令牌桶每秒填充平均速率。
    • key-resolver,用于限流的键的解析器的 Bean 对象的名字。它使用 SpEL 表达式根据#{@beanName}从 Spring 容器中获取 Bean 对象。
    1. 限流配置

    这里根据用户 ID 限流,请求路径中必须携带 userId 参数

    @Bean
    KeyResolver userKeyResolver() {
      return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
    }
    

    KeyResolver 需要实现 resolve 方法,比如根据 userid 进行限流,则需要用 userid 去判断。实现完 KeyResolver 之后,需要将这个类的 Bean 注册到 Ioc 容器中。

    如果需要根据 IP 限流,定义的获取限流 Key 的 bean 为:

    @Primary
    @Bean
    KeyResolver ipKeyResolver() {
      return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
    }
    

    通过 exchange 对象可以获取到请求信息,这边用了 HostName,如果你想根据用户来做限流的话这边可以获取当前请求的用户 ID 或者用户名就可以了,比如:

    如果需要根据接口的 URI 进行限流,则需要获取请求地址的 uri 作为限流 key,定义的 Bean 对象为:

    @Bean
    KeyResolver apiKeyResolver() {
      return exchange -> Mono.just(exchange.getRequest().getPath().value());
    }
    
    1. 完整的配置文件:
    @Component
    public class RateLimitConfig {
        @Bean
        KeyResolver userKeyResolver() {
            return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
        }
    
        @Primary
        @Bean
        KeyResolver ipKeyResolver() {
            return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
        }
    
        @Bean
        KeyResolver apiKeyResolver() {
            return exchange -> Mono.just(exchange.getRequest().getPath().value());
        }
    }
    

    限流演练

    这里我们用 postman 进行测试

    基于系统负载的动态限流

    在实际工作中,我们可能还需要根据网络连接数、网络流量、CPU 或内存负载等来进行动态限流。在这里我们以 CPU 为栗子。

    我们需要借助 Spring Boot Actuator 提供的 Metrics 能力进行实现基于 CPU 的限流 —— 当 CPU 使用率高于某个阈值就开启限流,否则不开启限流。

    我们在项目中引入 Actuator 的依赖坐标

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    

    然后基于过滤器和 metrics 指标判断是否需要限流。

    最后

    本文到此结束,感谢大家的阅读。欢迎关注公众号【当我遇上你】

  • 相关阅读:
    关于使用lombok遇到的问题
    Android自定义View之旅(二)继承View实现自定义
    Android自定义View之旅(一)自定义View的几种方式
    Android中attr属性的类型
    Android Studio 4.0 新功能与优化
    WebView播放视频白屏、不能全屏问题解决
    Android配置Scheme使用浏览器唤起APP的方式,以及不生效问题解决
    Android获取的IMEI只有14位问题解决
    Android偶遇杂症合集(持续更新)
    AndroidKeystore密钥库系统,保证本地加密算法的密钥安全性
  • 原文地址:https://www.cnblogs.com/idea360/p/12657070.html
Copyright © 2011-2022 走看看