SpringCloudGateway核心过滤器之请求限流详解-创新互联

环境:SpringBoot2.4.13 + Spring Cloud Gateway3.0.1

创新互联专注于长宁企业网站建设,响应式网站建设,电子商务商城网站建设。长宁网站建设公司,为长宁等地区提供建站服务。全流程定制网站制作,专业设计,全程项目跟踪,创新互联专业和态度为您提供的服务
概述

RequestRateLimiter GatewayFilter工厂使用一个RateLimiter实现来确定当前请求是否允许继续。如果不是,返回HTTP 429 - Too Many Requests(默认情况下)的状态。

该过滤器接受一个可选的keyResolver参数和特定于速率限制器的参数。该参数的作用就是用来根据你设定的规则生成key,比如在redis中使用什么key。

keyResolver是一个实现KeyResolver接口的bean。在配置中,使用SpEL按名称引用bean。#{@userKeyResolver}是一个SpEL表达式,它引用了一个名为userKeyResolver的bean。KeyResolver接口如下所示:

public interface KeyResolver {

	Monoresolve(ServerWebExchange exchange);

}

默认情况下,如果KeyResolver没有找到key,请求将被拒绝。你可以通过设置
spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key (true或false)和spring.cloud.gateway.filter.request-rate- limititer来调整这种行为。empty-key-status-code属性。

注意:RequestRateLimiter不能用“快捷方式”表示法进行配置。以下示例无效:

# INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
使用Redis限流

Redis的实现是基于Stripe所做的工作。它需要使用
spring-boot-starter-data-redis-reactive Spring Boot Starter。使用的算法是令牌桶算法。

计数器算法:有时间临界问题。

漏桶算法: 速率固定,有浪费资源问题。

配置属性说明:

redis-rate-limiter.replenishRate
允许用户在不丢弃任何请求的情况下每秒执行多少请求。这是令牌桶被填充的速率。
redis-rate-limiter.burstCapacity
允许用户在一秒钟内执行的大请求数。这是令牌桶可以容纳的令牌数量。将该值设置为零将阻止所有请求。
redis-rate-limiter.requestedTokens
一个请求花费多少令牌。这是为每个请求从桶中提取令牌的数量,默认为1。
  1. 一个稳定的速率是通过设置相同的值replenishRate和burstCapacity。
  2. 可以通过将burstCapacity设置为高于replenishRate来允许临时突发。

速率限制器需要在突发之间留出一段时间(根据replenishRate补发率),因为两个连续的爆发将导致丢弃的请求(HTTP 429 - Too Many requests)。

低于1个请求/秒的速率限制是通过以下方式实现的:将replenishRate设置为所需的请求数量,将requestedTokens设置为以秒为单位的时间跨度,将burstCapacity设置为replenishRate和requestedToken的乘积,例如,将replenishRate设为1,requestedTokens=60, burstCapability设置为60,将导致1 request/min的限制。

配置示例:

spring:
  cloud:
    gateway:
      default-filters:
      - StripPrefix=1
      routes:
      - id: o001
        uri: lb://order-service
        predicates:
        - Path=/api-a/**, /api-b/**
        filters:
        - name: RequestRateLimiter
          args:
            #每秒允许用户执行的请求数,而不丢弃任何请求。这是令牌桶的填充速率。
            redis-rate-limiter.replenishRate: 1
            #允许用户在一秒钟内完成的大请求数。这是令牌桶可以容纳的令牌数。将此值设置为零将阻止所有请求。
            redis-rate-limiter.burstCapacity: 2
            #一个请求需要多少令牌。这是每个请求从存储桶中获取的令牌数,默认为1。
            redis-rate-limiter.requestedTokens: 1
            keyResolver: "#{@userKeyResolver}"
            #自定义状态码
            #statusCode: INTERNAL_SERVER_ERROR
@Configuration
public class RedisRateConfig {

  @Bean
  public KeyResolver userKeyResolver() {
    // 以orderId限流
    // return exchange ->Mono.just(exchange.getRequest().getQueryParams().getFirst("orderId"));
    // 以ip限流
    return exchange ->Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()) ;
  }

}

解释:

这定义了每个IP1个请求速率的限制。允许2个请求的突发,但是在下一秒,只有1个请求可用。KeyResolver是一个获取用户请求参数的简单方法(注意,不建议在生产环境中使用)。

自定义限速器

还可以将速率限制器定义为实现RateLimiter接口的bean。在配置中,您可以使用SpEL按名称引用bean。#{@userRateLimiter}是一个SpEL表达式,它引用了一个名为userRateLimiter的bean。下面的清单定义了一个使用上一个清单中定义的KeyResolver的速率限制器:

spring:
  cloud:
    gateway:
      default-filters:
      - StripPrefix=1
      routes:
      - id: o001
        uri: lb://order-service
        predicates:
        - Path=/api-a/**, /api-b/**
        filters:
        - name: RequestRateLimiter
          args:
            rate-limiter: "#{@userRateLimiter}"
            keyResolver: "#{@userKeyResolver}"
public class UserRateLimiter implements RateLimiter{
  @Override
  public MapgetConfig() {
    return null;
  }
  @Override
  public ClassgetConfigClass() {
    return null;
  }
  @Override
  public Config newConfig() {
    return null;
  }
  @Override
  public MonoisAllowed(String routeId, String id) {
    return null;
  }
  public static class Config {
    @Min(1)
    private int replenishRate;
    @Min(0)
    private int burstCapacity = 1;
    @Min(1)
    private int requestedTokens = 1;
    public int getReplenishRate() {
      return replenishRate;
    }
    public Config setReplenishRate(int replenishRate) {
      this.replenishRate = replenishRate;
      return this;
    }
    public int getBurstCapacity() {
      return burstCapacity;
    }
    public Config setBurstCapacity(int burstCapacity) {
      this.burstCapacity = burstCapacity;
      return this;
    }
    public int getRequestedTokens() {
      return requestedTokens;
    }
    public Config setRequestedTokens(int requestedTokens) {
      this.requestedTokens = requestedTokens;
      return this;
    }
    @Override
    public String toString() {
      return new ToStringCreator(this).append("replenishRate", replenishRate)
        .append("burstCapacity", burstCapacity).append("requestedTokens", requestedTokens).toString();
    }
  }
}

完毕!!!

Spring Cloud Gateway核心过滤器之请求限流详解

原创2022-11-21 08:20·Spring全家桶实战案例

环境:SpringBoot2.4.13 + Spring Cloud Gateway3.0.1


概述

RequestRateLimiter GatewayFilter工厂使用一个RateLimiter实现来确定当前请求是否允许继续。如果不是,返回HTTP 429 - Too Many Requests(默认情况下)的状态。

该过滤器接受一个可选的keyResolver参数和特定于速率限制器的参数。该参数的作用就是用来根据你设定的规则生成key,比如在redis中使用什么key。

keyResolver是一个实现KeyResolver接口的bean。在配置中,使用SpEL按名称引用bean。#{@userKeyResolver}是一个SpEL表达式,它引用了一个名为userKeyResolver的bean。KeyResolver接口如下所示:

public interface KeyResolver {

	Monoresolve(ServerWebExchange exchange);

}

默认情况下,如果KeyResolver没有找到key,请求将被拒绝。你可以通过设置
spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key (true或false)和spring.cloud.gateway.filter.request-rate- limititer来调整这种行为。empty-key-status-code属性。

注意:RequestRateLimiter不能用“快捷方式”表示法进行配置。以下示例无效:

# INVALID SHORTCUT CONFIGURATION
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
使用Redis限流

Redis的实现是基于Stripe所做的工作。它需要使用
spring-boot-starter-data-redis-reactive Spring Boot Starter。使用的算法是令牌桶算法。

计数器算法:有时间临界问题。

漏桶算法: 速率固定,有浪费资源问题。

配置属性说明:

redis-rate-limiter.replenishRate
允许用户在不丢弃任何请求的情况下每秒执行多少请求。这是令牌桶被填充的速率。
redis-rate-limiter.burstCapacity
允许用户在一秒钟内执行的大请求数。这是令牌桶可以容纳的令牌数量。将该值设置为零将阻止所有请求。
redis-rate-limiter.requestedTokens
一个请求花费多少令牌。这是为每个请求从桶中提取令牌的数量,默认为1。
  1. 一个稳定的速率是通过设置相同的值replenishRate和burstCapacity。
  2. 可以通过将burstCapacity设置为高于replenishRate来允许临时突发。

速率限制器需要在突发之间留出一段时间(根据replenishRate补发率),因为两个连续的爆发将导致丢弃的请求(HTTP 429 - Too Many requests)。

低于1个请求/秒的速率限制是通过以下方式实现的:将replenishRate设置为所需的请求数量,将requestedTokens设置为以秒为单位的时间跨度,将burstCapacity设置为replenishRate和requestedToken的乘积,例如,将replenishRate设为1,requestedTokens=60, burstCapability设置为60,将导致1 request/min的限制。

配置示例:

spring:
  cloud:
    gateway:
      default-filters:
      - StripPrefix=1
      routes:
      - id: o001
        uri: lb://order-service
        predicates:
        - Path=/api-a/**, /api-b/**
        filters:
        - name: RequestRateLimiter
          args:
            #每秒允许用户执行的请求数,而不丢弃任何请求。这是令牌桶的填充速率。
            redis-rate-limiter.replenishRate: 1
            #允许用户在一秒钟内完成的大请求数。这是令牌桶可以容纳的令牌数。将此值设置为零将阻止所有请求。
            redis-rate-limiter.burstCapacity: 2
            #一个请求需要多少令牌。这是每个请求从存储桶中获取的令牌数,默认为1。
            redis-rate-limiter.requestedTokens: 1
            keyResolver: "#{@userKeyResolver}"
            #自定义状态码
            #statusCode: INTERNAL_SERVER_ERROR
@Configuration
public class RedisRateConfig {

  @Bean
  public KeyResolver userKeyResolver() {
    // 以orderId限流
    // return exchange ->Mono.just(exchange.getRequest().getQueryParams().getFirst("orderId"));
    // 以ip限流
    return exchange ->Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()) ;
  }

}

解释:

这定义了每个IP1个请求速率的限制。允许2个请求的突发,但是在下一秒,只有1个请求可用。KeyResolver是一个获取用户请求参数的简单方法(注意,不建议在生产环境中使用)。

自定义限速器

还可以将速率限制器定义为实现RateLimiter接口的bean。在配置中,您可以使用SpEL按名称引用bean。#{@userRateLimiter}是一个SpEL表达式,它引用了一个名为userRateLimiter的bean。下面的清单定义了一个使用上一个清单中定义的KeyResolver的速率限制器:

spring:
  cloud:
    gateway:
      default-filters:
      - StripPrefix=1
      routes:
      - id: o001
        uri: lb://order-service
        predicates:
        - Path=/api-a/**, /api-b/**
        filters:
        - name: RequestRateLimiter
          args:
            rate-limiter: "#{@userRateLimiter}"
            keyResolver: "#{@userKeyResolver}"
public class UserRateLimiter implements RateLimiter{
  @Override
  public MapgetConfig() {
    return null;
  }
  @Override
  public ClassgetConfigClass() {
    return null;
  }
  @Override
  public Config newConfig() {
    return null;
  }
  @Override
  public MonoisAllowed(String routeId, String id) {
    return null;
  }
  public static class Config {
    @Min(1)
    private int replenishRate;
    @Min(0)
    private int burstCapacity = 1;
    @Min(1)
    private int requestedTokens = 1;
    public int getReplenishRate() {
      return replenishRate;
    }
    public Config setReplenishRate(int replenishRate) {
      this.replenishRate = replenishRate;
      return this;
    }
    public int getBurstCapacity() {
      return burstCapacity;
    }
    public Config setBurstCapacity(int burstCapacity) {
      this.burstCapacity = burstCapacity;
      return this;
    }
    public int getRequestedTokens() {
      return requestedTokens;
    }
    public Config setRequestedTokens(int requestedTokens) {
      this.requestedTokens = requestedTokens;
      return this;
    }
    @Override
    public String toString() {
      return new ToStringCreator(this).append("replenishRate", replenishRate)
        .append("burstCapacity", burstCapacity).append("requestedTokens", requestedTokens).toString();
    }
  }
}

完毕!!!

图片

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


当前文章:SpringCloudGateway核心过滤器之请求限流详解-创新互联
网站URL:http://myzitong.com/article/jippc.html