百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

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

mhr18 2024-11-27 11:59 24 浏览 0 评论

环境: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应用详解1之谓词
Spring Cloud Gateway通过静态服务注册发现机制实现负载均衡
Spring Cloud Gateway应用详解2内置过滤器
SpringCloud Gateway 应用Hystrix 限流功能 自定义Filter详解
Spring Cloud Sentinel 流控限流
Spring Cloud Sentinel 熔断降级
Spring Cloud Function 快速入门

相关推荐

Spring Boot 分布式事务实现简单得超乎想象

环境:SpringBoot2.7.18+Atomikos4.x+MySQL5.71.简介关于什么是分布式事务,本文不做介绍。有需要了解的自行查找相关的资料。本篇文章将基于SpringBoot...

Qt编写可视化大屏电子看板系统15-曲线面积图

##一、前言曲线面积图其实就是在曲线图上增加了颜色填充,单纯的曲线可能就只有线条以及数据点,面积图则需要从坐标轴的左下角和右下角联合曲线形成完整的封闭区域路径,然后对这个路径进行颜色填充,为了更美观...

Doris大数据AI可视化管理工具SelectDB Studio重磅发布!

一、初识SelectDBStudioSelectDBStudio是专为ApacheDoris湖仓一体典型场景实战及其兼容数据库量身打造的GUI工具,简化数据开发与管理。二、Select...

RAD Studio 、Delphi或C++Builder设计代码编译上线缩短开发时间

#春日生活打卡季#本月,Embarcadero宣布RADStudio12.3Athens以及Delphi12.3和C++Builder12.3,提供下载。RADStudio12.3A...

Mybatis Plus框架学习指南-第三节内容

自动填充字段基本概念MyBatis-Plus提供了一个便捷的自动填充功能,用于在插入或更新数据时自动填充某些字段,如创建时间、更新时间等。原理自动填充功能通过实现com.baomidou.myba...

「数据库」Sysbench 数据库压力测试工具

sysbench是一个开源的、模块化的、跨平台的多线程性能测试工具,可以用来进行CPU、内存、磁盘I/O、线程、数据库的性能测试。目前支持的数据库有MySQL、Oracle和PostgreSQL。以...

如何选择适合公司的ERP(选erp系统的经验之谈)

很多中小公司想搞ERP,但不得要领。上ERP的目的都是歪的,如提高效率,减少人员,堵住财务漏洞等等。真正用ERP的目的是借机提升企业管理能力,找出管理上的问题并解决,使企业管理更规范以及标准化。上ER...

Manus放开注册,但Flowith才是Agent领域真正的yyds

大家好,我是运营黑客。前天,AIAgent领域的当红炸子鸡—Manus宣布全面放开注册,终于,不需要邀请码就能体验了。于是,赶紧找了个小号去确认一下。然后,额……就被墙在了外面。官方解释:中文版...

歌浓酒庄总酿酒师:我们有最好的葡萄园和最棒的酿酒师

中新网1月23日电1月18日,张裕董事长周洪江及总经理孙健一行在澳大利亚阿德莱德,完成了歌浓酒庄股权交割签约仪式,这也意味着张裕全球布局基本成型。歌浓:澳大利亚年度最佳酒庄据悉,此次张裕收购的...

软件测试进阶之自动化测试——python+appium实例

扼要:1、了解python+appium进行APP的自动化测试实例;2、能根据实例进行实训操作;本课程主要讲述用python+appium对APP进行UI自动化测试的例子。appium支持Androi...

为什么说Python是最伟大的语言?看图就知道了

来源:麦叔编程作者:麦叔测试一下你的分析能力,直接上图,自己判断一下为什么Python是最好的语言?1.有图有真相Java之父-JamesGoshlingC++之父-BjarneStrou...

如何在Eclipse中配置Python开发环境?

Eclipse是著名的跨平台集成开发环境(IDE),最初主要用来Java语言开发。但是我们通过安装不同的插件Eclipse可以支持不同的计算机语言。比如说,我们可以通过安装PyDev插件,使Eclip...

联合国岗位上新啦(联合国的岗位)

联合国人权事务高级专员办事处PostingTitleIntern-HumanRightsDutyStationBANGKOKDeadlineOct7,2025CategoryandL...

一周安全漫谈丨工信部:拟定超1亿条一般数据泄露属后果严重情节

工信部:拟定超1亿条一般数据泄露属后果严重情节11月23日,工信部官网公布《工业和信息化领域数据安全行政处罚裁量指引(试行)(征求意见稿)》。《裁量指引》征求意见稿明确了行政处罚由违法行为发生地管辖、...

oracle列转行以及C#执行语句时报错问题

oracle列转行的关键字:UNPIVOT,经常查到的怎么样转一列,多列怎么转呢,直接上代码(sshwomeyourcode):SELECTsee_no,diag_no,diag_code,...

取消回复欢迎 发表评论: