Gateway怎么实现限流的

Gateway怎么实现限流的

在API网关(如Spring Cloud Gateway、Kong、Nginx等)中实现限流是为了控制服务请求的频率,从而避免系统过载,确保稳定性和可用性。限流可以通过多种策略实现,常见的方法包括基于请求次数、时间窗口、IP地址等方式进行限制。下面是 Spring Cloud Gateway 实现限流的一些常见方式:

1. 基于请求次数的限流

这种方法通过限制单位时间内的请求次数来防止过多的请求访问服务。例如,限制每秒钟只能处理最多100个请求。

  • Spring Cloud Gateway实现: Spring Cloud Gateway提供了内置的限流功能,可以通过RequestRateLimiter过滤器来实现基于请求次数的限流。
示例配置:
spring:
  cloud:
    gateway:
      routes:
        - id: rate_limiter_route
          uri: http://example.com
          predicates:
            - Path=/api/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10  # 每秒钟请求的数量
                redis-rate-limiter.burstCapacity: 20  # 突发容量,即短时间内允许的最大请求数
  • replenishRate: 每秒钟允许的请求数。
  • burstCapacity: 突发容量,表示短时间内可以处理的最大请求数,超过该数的请求会被丢弃或拒绝。

2. 基于令牌桶算法(Token Bucket)限流

令牌桶算法是一种平滑请求流量的算法,它通过固定的速率生成令牌并将其存放在桶中,请求到达时需要获取令牌才能处理,如果令牌桶为空,则请求被拒绝。

  • Spring Cloud Gateway实现: 使用RequestRateLimiter实现基于令牌桶的限流。
示例配置:
spring:
  cloud:
    gateway:
      routes:
        - id: token_bucket_route
          uri: http://example.com
          predicates:
            - Path=/api/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10  # 每秒生成的令牌数
                redis-rate-limiter.burstCapacity: 20  # 令牌桶的容量

这里的配置和上面的请求次数限制类似,但背后实现的是令牌桶算法。

3. 基于IP限流

可以根据客户端IP地址来限制每个IP的请求频率,避免某个客户端过度访问服务。通常使用Redis来实现基于IP的限流。

示例配置(使用Redis):
spring:
  cloud:
    gateway:
      routes:
        - id: ip_rate_limiter_route
          uri: http://example.com
          predicates:
            - Path=/api/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20
                redis-rate-limiter.requestedTokens: 1
                redis-rate-limiter.keyResolver: "#{@ipKeyResolver}"

在这个例子中,keyResolver 指定了如何基于客户端 IP 地址来限流,可以自定义一个IP解析器ipKeyResolver,这样每个IP的请求次数会被限制。

4. 基于时间窗口的限流

时间窗口限流是按照固定的时间窗口(如每分钟、每小时等)来限制请求的数量。通过时间窗口来控制单位时间内的最大请求数。

示例配置:
spring:
  cloud:
    gateway:
      routes:
        - id: time_window_route
          uri: http://example.com
          predicates:
            - Path=/api/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 5  # 每秒钟请求的数量
                redis-rate-limiter.burstCapacity: 10  # 突发容量
                redis-rate-limiter.requestedTokens: 1  # 每次请求消耗的令牌数

这种方式将请求限制在一定的时间窗口内,如果在窗口内的请求数量超过限制,将拒绝额外的请求。

5. 自定义限流策略

Spring Cloud Gateway 还允许通过自定义KeyResolverRateLimiter等来实现更灵活的限流策略。例如,基于用户的ID、API路径等来做不同的限流策略。

自定义 KeyResolver 示例:
@Bean
public KeyResolver ipKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostString());
}

这个例子通过客户端IP地址进行限流。

6. 其他网关限流工具

除了Spring Cloud Gateway,其他网关如 KongNginx 等也提供了丰富的限流功能:

  • Kong 使用插件机制实现限流,支持基于请求次数、IP、API Key等的限流。
  • Nginx 可以通过 limit_req 和 limit_conn 模块来进行限流控制。

总结

Spring Cloud Gateway 中,常见的限流方式包括:

  • 基于请求次数的限流(Rate Limiting)
  • 基于令牌桶算法的限流(Token Bucket)
  • 基于IP的限流
  • 基于时间窗口的限流

可以通过RequestRateLimiter过滤器实现这些策略,结合 Redis 等存储技术来共享和持久化限流状态。在选择限流策略时,需要根据业务需求、流量模式、以及系统的负载能力来决定。

分析Gateway 限流代码


@Component
public class RateLimitConfig {

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


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

    @Bean
    KeyResolver apiKeyResolver() {
	return exchange -> Mono.just(exchange.getRequest().getPath().value());
    }

    @Primary
    @Bean
    KeyResolver appIpKeyResolver() {
	return exchange -> {
	    Route route = (Route) exchange.getAttributes().get(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
	    return Mono.just(exchange.getRequest().getRemoteAddress().getHostName().concat(route.getUri().getHost()));
	};
    }
}

这段代码实现了Spring Cloud Gateway的限流配置,具体的实现通过不同的KeyResolver来为请求提供唯一的标识,用于区分不同的请求来源或策略。KeyResolver是限流的核心组成部分,它决定了限流的“键”(即每个请求的唯一标识),从而确保不同的请求按照不同的规则被限流。

以下是对代码的详细分析:

1. KeyResolver 的作用

KeyResolver 是 Spring Cloud Gateway 中限流机制的一部分,用来生成与请求相关的唯一“键”。在限流时,基于这些“键”来计算每个限流单元(例如每个用户、每个IP、每个API等)的请求次数。限流规则会依据这些键来进行流量控制。

2. userKeyResolver

 

java

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

  • 功能:该 KeyResolver 基于请求的查询参数 token 生成唯一的限流键。
  • 应用场景:当客户端使用 token 参数(可能是API Key或用户身份标识符)时,可以基于该 token 对每个用户进行限流。每个用户(或每个 token)的请求次数将被单独计数。
  • 具体实现:从请求的查询参数中获取 token 参数的第一个值。如果没有这个参数,返回 null 或空值会导致限流功能不生效。

3. ipKeyResolver

 

java

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

  • 功能:该 KeyResolver 基于客户端的 IP 地址生成限流键。
  • 应用场景:当需要限制每个IP地址的请求频率时,使用此 KeyResolver。例如,可以限制每个IP在一定时间窗口内的请求次数,从而避免单个IP的过多请求对系统造成压力。
  • 具体实现:通过 exchange.getRequest().getRemoteAddress() 获取客户端的远程IP地址,然后使用 getHostName() 获取IP的主机名。理论上,getHostName() 会尝试解析IP地址为主机名,但在某些情况下,可能直接返回IP地址。

4. apiKeyResolver

 

java

@Bean KeyResolver apiKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getPath().value()); }

  • 功能:该 KeyResolver 基于请求的API路径生成唯一的限流键。
  • 应用场景:当需要限制某个API路径的请求频率时,使用此 KeyResolver。例如,限制 /api/v1/login 或 /api/v1/register 路径的访问频率,可以防止某个特定API被过度访问。
  • 具体实现:通过 exchange.getRequest().getPath().value() 获取请求的路径。这个路径通常是 URI 的路径部分,如 /api/v1/resource

5. appIpKeyResolver

 

java

@Primary @Bean KeyResolver appIpKeyResolver() { return exchange -> { Route route = (Route) exchange.getAttributes().get(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR); return Mono.just(exchange.getRequest().getRemoteAddress().getHostName().concat(route.getUri().getHost())); }; }

  • 功能:该 KeyResolver 综合了客户端的 IP 地址和路由的 URI 来生成限流键。
  • 应用场景:当希望根据客户端 IP 和访问的具体服务进行限流时,使用此 KeyResolver。例如,可以限制每个IP对特定API的访问频率。
  • 具体实现
    • 通过 exchange.getRequest().getRemoteAddress().getHostName() 获取客户端的 IP 地址。
    • 通过 exchange.getAttributes().get(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR) 获取当前请求的路由信息。
    • route.getUri().getHost() 获取请求目标服务的主机名(或域名),并将其与客户端IP拼接,作为限流的唯一键。
    • 使用 concat() 方法将客户端IP与目标服务主机名合并为一个字符串,以保证限流的独立性。

6. @Primary 注解

 

java

@Primary @Bean KeyResolver appIpKeyResolver() { ... }

  • 作用:在有多个相同类型的 @Bean 时,@Primary 注解表示优先使用该 Bean。如果在其他地方有 KeyResolver 的注入需求,Spring 将默认使用 appIpKeyResolver() 方法返回的实例。
  • 场景:当存在多个 KeyResolver 时,如果没有明确指定使用哪个 KeyResolver,Spring 会自动选择标记为 @Primary 的那个。这里标记了 appIpKeyResolver 为默认的 KeyResolver

总结

这段代码定义了多个 KeyResolver,并为不同的限流策略提供了可选择的实现:

  1. userKeyResolver:基于请求的 token 限流,适用于基于用户或身份的限流。
  2. ipKeyResolver:基于客户端 IP 地址限流,适用于限制每个IP的请求次数。
  3. apiKeyResolver:基于请求路径限流,适用于限制某个特定API的访问。
  4. appIpKeyResolver:基于客户端 IP 地址和路由的 URI 组合限流,适用于更细粒度的限流需求,确保同一IP对不同API的请求可以独立计数。

@Primary 注解确保 appIpKeyResolver 是默认的限流键生成器,除非特别指定,否则会优先使用它。

这些 KeyResolver 会与 RequestRateLimiter 等限流功能配合使用,从而在 API 网关层实现精细化的限流控制。

怎么没有指定限流的量,每秒允许访问的量

在这段代码中,虽然定义了不同的 KeyResolver 来生成限流的标识符(如 tokenIPAPI路径),但确实没有指定实际的限流规则(例如每秒允许的访问量)。限流的具体控制是通过 Spring Cloud Gateway 的 RequestRateLimiter 过滤器来实现的,而这个过滤器是用来根据指定的规则对请求进行限流的。

要实现每秒允许的访问量,你需要配置 RequestRateLimiter 过滤器,并为它指定限流规则(如每秒最大访问量和最大突发流量)。

完整的限流配置示例

首先,你需要创建一个 RequestRateLimiter 过滤器,并在过滤器中配置限流策略。通常,你可以通过如下方式来配置:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cloud.gateway.filter.ratelimit.RequestRateLimiter;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.config.GlobalFilterAutoConfiguration;

@Configuration
public class GatewayConfig {

    @Bean
    public RequestRateLimiter filter(KeyResolver keyResolver) {
        // 配置限流:每秒最多允许 10 次请求,突发流量最多为 20 次
        return new RequestRateLimiter()
                .setRateLimiter(new MyRateLimiter(10, 20))  // 每秒 10 次请求,突发流量最多 20 次
                .setKeyResolver(keyResolver); // 设置限流的 KeyResolver
    }

    // 自定义一个简单的 RateLimiter 实现类
    public static class MyRateLimiter implements RateLimiter {
        private final int replenishRate;
        private final int burstCapacity;

        public MyRateLimiter(int replenishRate, int burstCapacity) {
            this.replenishRate = replenishRate;
            this.burstCapacity = burstCapacity;
        }

        @Override
        public boolean isAllowed(String key) {
            // 此处实现你自己的限流逻辑,可以借助令牌桶算法、漏桶算法等
            return true;  // 只是示例,实际需要实现限流逻辑
        }

        // 配置每秒最大请求数(每秒 10 次)
        public int getReplenishRate() {
            return replenishRate;
        }

        // 配置突发容量
        public int getBurstCapacity() {
            return burstCapacity;
        }
    }
}

如何将限流规则与 KeyResolver 配合?

在这段代码中,RequestRateLimiter 的限流规则(如每秒允许 10 次请求,突发容量为 20)会与之前定义的 KeyResolver 配合,限制特定 token、IP 或 API 路径的访问频率。

  1. KeyResolver 选择:可以使用你之前定义的 userKeyResolveripKeyResolverapiKeyResolver 来作为限流的依据。

  2. 限流逻辑:通过 MyRateLimiter 类实现限流逻辑(如令牌桶、漏桶等算法)。每个限流的“key”(例如 tokenIP)会根据配置的规则(如每秒 10 次、突发流量 20 次)进行访问次数的限制。

示例配置:按 token 限流

假设你想基于 token 进行限流,你可以这样配置:

@Bean
public RequestRateLimiter filter(KeyResolver userKeyResolver) {
    return new RequestRateLimiter()
            .setRateLimiter(new MyRateLimiter(10, 20))  // 每秒 10 次请求,突发流量最多 20 次
            .setKeyResolver(userKeyResolver);  // 使用之前定义的基于 token 的 KeyResolver
}

限流的配置项

  1. replenishRate:每秒允许的请求数。例如,10 表示每秒最多可以处理 10 个请求。

  2. burstCapacity:突发容量,表示在短时间内可以允许的最大请求数。例如,20 表示最多允许瞬间访问 20 次,但通常会平滑地恢复到正常的请求速率。

  3. KeyResolver:你已经定义了多个 KeyResolver,它们决定了限流的粒度。你可以按用户(token)、IP 地址、路径等来分别限流。

总结

这段代码本身只是定义了限流的标识符(通过 KeyResolver)。真正的限流控制需要通过 RequestRateLimiter 过滤器来实现,并在其中指定限流的具体限制量(如每秒允许多少次请求)。你可以使用 replenishRateburstCapacity 来配置每秒允许的访问量及突发流量。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT c++ 样式 设置 按钮(QPushButton)的渐变色美化

上一篇文章中描述了标签的渐变色美化,本文描述按钮的渐变色美化。 1.头文件 #ifndef WIDGET_H #define WIDGET_H #include <QWidget> //#include "CustomButton.h"#include <QVBoxLayout> #include <QLinearGradient> #include <QPushButton&…

OPT: Open Pre-trained Transformer语言模型

摘要 大规模语言模型通常需要数十万计算日的训练时间&#xff0c;展现了在零样本和小样本学习中的显著能力。鉴于其计算成本之高&#xff0c;这些模型在没有大量资本投入的情况下难以复现。对于那些通过API提供的少数模型&#xff0c;研究者无法获取完整的模型权重&#xff0c…

力扣257(关于回溯算法)二叉树的所有路径

257. 二叉树的所有路径 一.问题描述 已解答 简单 相关标签 相关企业 给你一个二叉树的根节点 root &#xff0c;按 任意顺序 &#xff0c;返回所有从根节点到叶子节点的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,null,5…

《OpenCV计算机视觉实战项目》——银行卡号识别

文章目录 项目任务及要求项目实现思路项目实现及代码导入模块设置参数对模版图像中数字的定位处理银行卡的图像处理读取输入图像&#xff0c;预处理找到数字边框使用模版匹配&#xff0c;计算匹配得分 画出并打印结果 项目任务及要求 任务书&#xff1a; 要为某家银行设计一套…

Python学习(三)基础入门(数据类型、变量、条件判断、模式匹配、循环)

目录 一、第一个 Python 程序1.1 命令行模式、Python 交互模式1.2 Python的执行方式1.3 SyntaxError 语法错误1.4 输入和输出 二、Python 基础2.1 Python 语法2.2 数据类型1&#xff09;Number 数字2&#xff09;String 字符串3&#xff09;List 列表4&#xff09;Tuple 元组5&…

系统思考—要素连接

“改变你的思维&#xff0c;就能改变你的世界”— 诺曼皮尔 世界上的所有事物&#xff0c;都在规律的支配下&#xff0c;以系统的方式运转。显性的部分是我们能看到的“要素”&#xff0c;而那些看不见的力量&#xff0c;正是推动系统运作的要素之间的相互作用。更隐秘的&…

云原生(1)

作业&#xff1a; 1、shell 脚本写出检测 /tmp/size.log 文件如果存在显示它的内容&#xff0c;不存在则创建一个文件将创建时间写入。 2、写一个 shel1 脚本,实现批量添加 20个用户,用户名为user01-20,密码为user 后面跟5个随机字符。 3、编写个shel 脚本将/usr/local 日录下大…

【IO编程】文件IO的API

这篇文章在 文章&#xff1a;【文件I/O】文件持久化 的基础之上&#xff0c;更进一步的描述了文件IO中更多更详细的API详解。 文件IO 文件IO操作是必须要理解的环节之一&#xff0c;因为 s&#xff1a;套接字文件 &#xff1b;p: 管道文件 —> 都需要通过文件IO来进行打开…

【数据库】Unity 使用 Sqlite 数据库

1.找到需要三个 DLL Mono.Data.Sqlite.dllSystem.Data.dllsqlite3.dll 上面两个dll可在本地unity安装目录找到&#xff1a; C:\Program Files\Unity\Hub\Editor\2022.3.xxf1c1\Editor\Data\MonoBleedingEdge\lib\mono\unityjit-win32 下面dll可在sqlite官网下载到&#xff…

省级-农业科技创新(农业科技专利)数据(2010-2022年)-社科数据

省级-农业科技创新&#xff08;农业科技专利&#xff09;数据&#xff08;2010-2022年&#xff09;-社科数据https://download.csdn.net/download/paofuluolijiang/90028570 https://download.csdn.net/download/paofuluolijiang/90028570 数据 年份、省份、农业科技专利数量…

51单片机——定时器中断(重点)

STC89C5X含有3个定时器&#xff1a;定时器0、定时器1、定时器2 注意&#xff1a;51系列单片机一定有基本的2个定时器&#xff08;定时器0和定时器1&#xff09;&#xff0c;但不全有3个中断&#xff0c;需要查看芯片手册&#xff0c;通常我们使用的是基本的2个定时器&#xff…

计算机的错误计算(二百零九)

摘要 利用两个大模型判断 是否为有理数&#xff1f;其值是多少&#xff1f;由实验知&#xff0c;其中一个大模型判断错误&#xff0c;说不是有理数&#xff1b;至于其值&#xff0c;该大模型选了一个错误的数值。 例1. e^(45*ln(24.8))是有理数吗&#xff1f;其值是多少&am…

Facebook 隐私变革之路:回顾与展望

在数字时代&#xff0c;个人隐私的保护一直是社交平台面临的重大挑战之一。作为全球最大的社交网络平台&#xff0c;Facebook&#xff08;现为Meta&#xff09;在处理用户隐私方面的变革&#xff0c;历经了多次调整与完善。本文将回顾Facebook在隐私保护方面的历程&#xff0c;…

第432场周赛:跳过交替单元格的之字形遍历、机器人可以获得的最大金币数、图的最大边权的最小值、统计 K 次操作以内得到非递减子数组的数目

Q1、跳过交替单元格的之字形遍历 1、题目描述 给你一个 m x n 的二维数组 grid&#xff0c;数组由 正整数 组成。 你的任务是以 之字形 遍历 grid&#xff0c;同时跳过每个 交替 的单元格。 之字形遍历的定义如下&#xff1a; 从左上角的单元格 (0, 0) 开始。在当前行中向…

GitLab CI/CD使用runner实现自动化部署前端Vue2 后端.Net 7 Zr.Admin项目

1、查看gitlab版本 建议安装的runner版本和gitlab保持一致 2、查找runner 执行 yum list gitlab-runner --showduplicates | sort -r 找到符合gitlab版本的runner&#xff0c;我这里选择 14.9.1版本 如果执行出现找不到下载源&#xff0c;添加官方仓库 执行 curl -L &quo…

机器学习基础-机器学习的常用学习方法

目录 半监督学习的概念 规则学习的概念 基本概念 机器学习里的规则 逻辑规则 规则集 充分性与必要性 冲突消解 命题逻辑 → 命题规则 序贯覆盖 单条规则学习 剪枝优化 强化学习的概念 1. 强化学习对应了四元组 2. 强化学习的目标 强化学习常用马尔可夫决策过程…

docker安装rabbit后访问报错最佳的几种解决方案

错误通常是由于RabbitMQ的安全配置导致的&#xff0c;RabbitMQ默认配置允许的用户仅能通过localhost访问。这通常出现在RabbitMQ的guest用户上&#xff0c;guest用户默认只能从localhost登录&#xff0c;而无法从其他IP地址进行远程访问。 解决方法&#xff1a; 1. **创建一个…

26个开源Agent开发框架调研总结(2)

根据Markets & Markets的预测&#xff0c;到2030年&#xff0c;AI Agent的市场规模将从2024年的50亿美元激增至470亿美元&#xff0c;年均复合增长率为44.8%。 Gartner预计到2028年&#xff0c;至少15%的日常工作决策将由AI Agent自主完成&#xff0c;AI Agent在企业应用中…

第 32 章 - Elasticsearch 的应用场景与技术解决方案

思维导图 0. 简介 Elasticsearch 主要应用于搜索场景。场景的如 应用内的搜索框、还有日志搜索等。 下面将介绍 Elasticsearch 在开发中的常见应用场景。 1. 日志搜索 日志搜索是最常见的应用。 其组合技术为&#xff1a;Kafka、Logstash、Elasticsearch、Kibana 该组合整体…

VsCode对Arduino的开发配置

ps&#xff1a;我的情况是在对esp32进行编译、烧录时&#xff0c;找不到按钮&#xff0c;无法识别Arduino文件&#xff0c;适合已经有ini文件的情况。 1.在vscode中安装拓展 2.打开设置&#xff0c;点击右上角&#xff0c;转到settings.json文件 3.复制以下代码并保存 {"…