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

news2024/11/24 1:50:41

环境: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 {

	Mono<String> resolve(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. 一个稳定的速率是通过设置相同的值replenishRateburstCapacity
  2. 可以通过将burstCapacity设置为高于replenishRate来允许临时突发。

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

低于1个请求/秒的速率限制是通过以下方式实现的:将replenishRate设置为所需的请求数量,将requestedTokens设置为以秒为单位的时间跨度,将burstCapacity设置为replenishRaterequestedToken的乘积,例如,将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<UserRateLimiter.Config> {
  @Override
  public Map<String, Config> getConfig() {
    return null;
  }
  @Override
  public Class<Config> getConfigClass() {
    return null;
  }
  @Override
  public Config newConfig() {
    return null;
  }
  @Override
  public Mono<Response> isAllowed(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 {

	Mono<String> resolve(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. 一个稳定的速率是通过设置相同的值replenishRateburstCapacity
  2. 可以通过将burstCapacity设置为高于replenishRate来允许临时突发。

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

低于1个请求/秒的速率限制是通过以下方式实现的:将replenishRate设置为所需的请求数量,将requestedTokens设置为以秒为单位的时间跨度,将burstCapacity设置为replenishRaterequestedToken的乘积,例如,将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<UserRateLimiter.Config> {
  @Override
  public Map<String, Config> getConfig() {
    return null;
  }
  @Override
  public Class<Config> getConfigClass() {
    return null;
  }
  @Override
  public Config newConfig() {
    return null;
  }
  @Override
  public Mono<Response> isAllowed(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();
    }
  }
}

完毕!!!

图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/64818.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于51单片机的贪吃蛇游戏设计

1绪 论 1.1本课题研究的背景及意义 随着当今社会的发展&#xff0c;人们的生活节奏变得越来越快&#xff0c;人们开始逐渐的融入全球化的世界。人们已经不再局限于一小块天地&#xff0c;加班&#xff0c;出差已经占据了现代人生活的绝大部分。这个时候&#xff0c;一款简单易携…

ChatGPT 体验和思考

一、体验 1、辅助写代码 2、检查代码&#xff08;遗憾的是&#xff0c;不一定是对的&#xff09; 3、分析代码 4、帮你了解/入门一项陌生的技术 小结&#xff1a; AI 会慢慢成为程序员的得力帮手&#xff0c;但目前来看&#xff0c;似乎还是不够成熟。 当然&#xff0c;大多…

《软件工程》2013年期末试卷

北京信息科技大学《软件工程》2013年期末试卷

青岛山水新城二期景观设计 全套设计

目录 1前言 2 1.1 青岛市地理位置与自然概况 2 1.2 山水新城小区概况 3 1.3设计的目的和意义 4 1.4小区园林景观设计现状和发展趋势 5 2本论 6 2.1设计依据 6 2.1.1 平面规划图 6 2.1.2 国家及地方有关规定及标准 6 2.2 设计指导思想 6 2.2.1 “以人为本”的设计理念 6 2.2.2 “…

PHP毕业设计毕设辅导课(1):PHP 基础语法

PHP 基础语法 PHP 脚本在服务器上执行&#xff0c;然后将纯 HTML 结果发送回浏览器。 PHP 基本的语法和输出 PHP 脚本可以放在文档中的任何位置。 <?php // PHP 代码 ?>PHP 脚本以 <?php 开始&#xff0c;以 ?> 结束&#xff0c;代码示例如下&#xff1a; …

[附源码]Python计算机毕业设计Django天狗电子商城系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

用Prophet在Python中进行时间序列预测

预测通常被认为是报告的发展。报告可以帮助我们回答&#xff0c;发生了什么事&#xff1f;预测有助于回答下一个逻辑问题&#xff0c;将会发生什么&#xff1f; 最近我们被客户要求撰写关于时间序列预测的研究报告&#xff0c;包括一些图形和统计输出。 Prophet的目的是“使专…

[附源码]Python计算机毕业设计Django酒店客房管理信息系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;我…

问题解决:记录一次Linux服务器根目录突然爆满

一、出问题了 过了个双休来到公司&#xff0c;同时发现Linux终端的服务器状态中根目录空间直接爆满100%&#xff0c;周五走之前根目录仅仅使用了59%&#xff0c;同时项目服务的后台不停的有日志打印&#xff0c;而且测试的小伙伴说系统登录不上去了。下面记录一下个人排查并解…

CORTEX-A7芯片中断系统基本原理与控制方法

大家好&#xff0c;今天主要和大家聊一聊&#xff0c;如何使用高端芯片的中断系统的方法。 目录 第一&#xff1a;中断的基本简介 ​第二&#xff1a;GIC控制器介绍 第一&#xff1a;中断的基本简介 中断系统是一个处理器重要的组成部分&#xff0c;中断系统极大的提高了CPU的…

Webpack5 快速入门

1. webpack 介绍 2. webpack 基本使用 3. webpack 5大核心概念 4. webpack 配置文件 5. webpack 运行脚本 6. webpack 处理样式资源 一、处理 css 资源 二、处理 less 资源 三、处理 scss 资源 四、处理 stylus 资源 7. webpack 处理图片资源 8. webpack 文件输出目录…

[附源码]计算机毕业设计基于Springboot校园租赁系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【STM32学习(4)】STM32简述定时器

一、什么是定时器 有计时和定时功能的仪器组件——对于芯片来说&#xff0c;定时器含有计时和定时功能&#xff0c;片内模块——TIM 二、STM32F4xx系列定时器分类 片内外设定时器&#xff08;14个&#xff09; 高级定时器&#xff1a;TIM1、TIM8通用定时器&#xff1a;TIM2…

SASE和零信任--傻傻分不清楚

零信任和SASE&#xff0c;分别来自于两家世界级咨询公司Forrester与Gartner。 首先&#xff0c;Forrester提出零信任&#xff0c;成为近十年来最重要的安全创新理念。然后&#xff0c;Gartner提出SASE&#xff08;安全访问服务边缘&#xff09;&#xff0c;在零信任的基础上面…

[附源码]计算机毕业设计天狗电子商城系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【浅学Java】SpringBoot 配置文件

SpringBoot 配置文件1. 配置文件的作用2. 配置文件的格式.properties配置文件的格式.properties配置文件的缺点.yml配置文件的格式.yml配置文件的优点3. 配置文件的分类3.1 两种类型配置文件3.2 用户自定义配置项4. 配置信息读取4.1 自定义配置信息读取4.2 系统配置信息读取4.3…

MySQL高可用方案之MHA

目录 一、简介 二、MHA特点 三、搭建MySQL MHA 1、安装MHA 2、在所有服务器上配置无密码认证 3、在manager节点上配置MHA 4、 manager节点编辑配置文件&#xff0c;管理 mysql 节点服务器 5、在Master服务器上手动开启vip 6、在 manager 节点上测试 ssh 无密码认证 7、…

安装JDK8绿色版

前言&#xff1a;官网提供的JDK8只有安装包&#xff0c;没有绿色免安版&#xff0c;而我们开发时需要根据需求使用不同的JDK版本&#xff0c;使用安装包安装过程会写入注册表&#xff0c;不方便便携式使用&#xff0c;还会附带安装Java 8 Update&#xff0c;会自动更新。而绿色…

详细介绍NLP中文分词原理及分词工具

基于词表的分词方法 正向最大匹配算法FMM 从左到右扫描文本&#xff0c;得到词的最大匹配。 案例分析&#xff1a; 用正向最大匹配法对“秦皇岛今天晴空万里”进行中文分词&#xff0c;见下表。 词典 &#xff1a;“秦皇岛”“岛”“今天”“天晴”“晴空万里”“万里”………

《数据在外设中的存储》

【一】磁盘的物理结构 我们现在很少看到磁盘了&#xff0c;我们电脑使用的大部分使用的是nvme协议的固态硬盘&#xff0c;差一点的使用的是sata固态接口的硬盘了&#xff0c;磁盘在我们电脑上尤其是笔记本电脑上是很少存在的&#xff0c;难道磁盘真的穷途末路了吗&#xff1f;显…