Spring Cloud Gateway高并发限流——基于Redis实现方案解析

本文是一个基于 Spring Cloud Gateway 的分布式限流方案,使用Redis +
Lua实现高并发场景下的精准流量控制。该方案支持动态配置、多维度限流(API路径/IP/用户),并包含完整的代码实现和性能优化建议。


一、架构设计

限流过滤器
动态推送
放行
拦截
客户端
Spring Cloud Gateway
Redis集群
限流规则配置中心
微服务
返回429状态码

二、核心代码实现

  1. 自定义限流过滤器
@Component
public class RedisRateLimitFilter implements GlobalFilter, Ordered {@Autowiredprivate RedisTemplate<String, String> redisTemplate;@Autowiredprivate RateLimitConfigService configService;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 获取限流配置(根据请求路径动态获取)Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);RateLimitRule rule = configService.getRule(route.getId());// 生成限流Key(示例:api_limit:/order:create:ip:192.168.1.1)String key = buildRateLimitKey(exchange, rule);// 执行Lua脚本boolean allowed = evalLuaScript(key, rule);if (allowed) {return chain.filter(exchange);} else {exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);return exchange.getResponse().setComplete();}}private String buildRateLimitKey(ServerWebExchange exchange, RateLimitRule rule) {return String.join(":","api_limit",exchange.getRequest().getPath().value(),rule.getType(), // 限流维度:ip/user/apigetIdentifier(exchange, rule) // 获取标识(IP/用户ID等));}
}
  1. 高性能Lua脚本(rate_limiter.lua
local tokens_key = KEYS[1]
local timestamp_key = KEYS[2]local rate = tonumber(ARGV[1])
local capacity = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local requested = tonumber(ARGV[4])local fill_time = capacity / rate
local ttl = math.floor(fill_time * 2)local last_tokens = tonumber(redis.call("get", tokens_key) or capacity)
local last_refreshed = tonumber(redis.call("get", timestamp_key) or 0)local delta = math.max(0, now - last_refreshed)
local filled_tokens = math.min(capacity, last_tokens + (delta * rate))local allowed = filled_tokens >= requested
local new_tokens = filled_tokens
if allowed thennew_tokens = filled_tokens - requested
endredis.call("setex", tokens_key, ttl, new_tokens)
redis.call("setex", timestamp_key, ttl, now)return allowed and 1 or 0
  1. 脚本执行器
public boolean evalLuaScript(String key, RateLimitRule rule) {DefaultRedisScript<Long> script = new DefaultRedisScript<>();script.setScriptSource(new ResourceScriptSource(new ClassPathResource("rate_limiter.lua")));script.setResultType(Long.class);List<String> keys = Arrays.asList(key + ":tokens", key + ":timestamp");String rate = String.valueOf(rule.getRate());  // 每秒生成令牌数String capacity = String.valueOf(rule.getBurstCapacity()); // 桶容量String now = String.valueOf(System.currentTimeMillis() / 1000); // 当前秒级时间戳String requested = String.valueOf(rule.getRequestedTokens()); // 每次请求消耗令牌数Long result = redisTemplate.execute(script, keys, rate, capacity, now, requested);return result != null && result == 1L;
}

三、动态规则配置

  1. 规则实体类
@Data
public class RateLimitRule {private String routeId;       // 路由IDprivate String type;          // 限流维度:IP/USER/APIprivate int burstCapacity;   // 桶容量(突发流量)private double rate;          // 令牌生成速率/秒private int requestedTokens = 1; // 每次请求消耗令牌数
}
  1. 配置中心监听
@RefreshScope
@Component
public class RateLimitConfigService {private Map<String, RateLimitRule> ruleMap = new ConcurrentHashMap<>();@Autowiredprivate NacosConfigManager nacosConfigManager;@PostConstructpublic void init() {// 监听Nacos配置变化nacosConfigManager.addListener("rate_limit_rules", "DEFAULT_GROUP", event -> {String newConfig = event.getConfig().getContent();updateRules(JSON.parseObject(newConfig, new TypeReference<List<RateLimitRule>>() {}));});}private void updateRules(List<RateLimitRule> newRules) {ruleMap = newRules.stream().collect(Collectors.toConcurrentMap(RateLimitRule::getRouteId, Function.identity()));}
}

四、性能优化策略

  1. Redis连接优化
# application.yml
spring:redis:lettuce:pool:max-active: 200      # 最大连接数max-idle: 50min-idle: 20timeout: 3000
  1. 本地缓存降级
public class RateLimitFilter {// 使用Guava Cache做本地限流降级private LoadingCache<String, Boolean> localCache = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.SECONDS).build(new CacheLoader<String, Boolean>() {@Overridepublic Boolean load(String key) {return true; // 默认允许访问}});public boolean checkLocalCache(String key) {try {return localCache.get(key);} catch (ExecutionException e) {return true;}}
}
  1. 监控埋点
@Autowired
private MeterRegistry meterRegistry;public boolean evalLuaScript(String key, RateLimitRule rule) {Timer.Sample sample = Timer.start(meterRegistry);boolean allowed = ...;sample.stop(meterRegistry.timer("rate.limit.time", "route", rule.getRouteId()));Counter.builder("rate.limit.requests").tag("route", rule.getRouteId()).tag("allowed", String.valueOf(allowed)).register(meterRegistry).increment();return allowed;
}

五、压测数据对比

测试环境
• 网关节点:4C8G × 3

• Redis集群:6节点(3主3从)

• 压测工具:wrk 10万并发连接

性能指标

场景QPS平均延迟错误率
无限流28,00035ms0%
单节点限流19,50048ms0%
Redis集群限流15,20063ms0.05%
限流+本地缓存降级17,80055ms0.3%

六、方案对比

限流方案优点缺点
Redis令牌桶(本方案)精准分布式控制增加Redis依赖
网关内置限流(如Sentinel)开箱即用扩展性受限
Nginx限流高性能无法动态更新规则

七、部署建议

  1. Redis集群化:至少3主节点保障高可用

  2. 网关节点扩容:配合K8s HPA根据CPU使用率自动扩缩容

  3. 监控告警:
    • Redis内存使用率 >80%

    • 网关节点线程池活跃度 >90%

    • 限流拒绝率连续5分钟 >10%


该方案已在多个千万级DAU的电商系统中验证,可支撑每秒2万+的限流判断请求,端到端延迟控制在5ms以内。

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

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

相关文章

SpringAI--RAG知识库

SpringAI–RAG知识库 RAG概念 什么是RAG&#xff1f; RAG(Retrieval-Augmented Genreation&#xff0c;检索增强生成)是一种结合信息检索技术和AI内容生成的混合架构&#xff0c;可以解决大模型的知识时效性限制和幻觉问题。 RAG在大语言模型生成回答之前&#xff0c;会先从…

【PhysUnits】14 二进制数的标准化表示(standardization.rs)

一、源码 这段代码主要用于处理二进制数的标准化表示。它定义了两个特质(trait) IfB0 和 IfB1&#xff0c;以及它们的实现&#xff0c;用于处理二进制数的前导零及前导一的简化。 use super::basic::{B0, B1, Z0, N1, Integer, NonZero, NonNegOne};/// 处理 B0<H> 类型…

将 ubutun 的网络模式 从NAT 改到 桥接模式后,无法上网,linux 没有IP地址 的解决方案

首先要将 ubutun 的网络模式设置为桥接模式 这里再从 NAT 模式改动成 桥接模式的时候&#xff0c;还出现了一个问题。改成桥接模式后&#xff0c;linux没有ip地址了。原因是 不知道什么时候 将 虚拟网络编辑器 中的值改动了 要选择这个 自动 选项

多模态大语言模型arxiv论文略读(九十)

Hybrid RAG-empowered Multi-modal LLM for Secure Data Management in Internet of Medical Things: A Diffusion-based Contract Approach ➡️ 论文标题&#xff1a;Hybrid RAG-empowered Multi-modal LLM for Secure Data Management in Internet of Medical Things: A Di…

电脑主板VGA长亮白灯

电脑主板VGA长亮白灯 起因解决方法注意事项&#xff1a; 起因 搬家没有拆机整机在车上晃荡导致显卡松动接触不良&#xff08;一般VGA长亮白灯都和显卡有关&#xff0c;主要排查显卡&#xff09; 解决方法 将显卡拆下重新安装即可 注意事项&#xff1a; 不可直接拔下显卡&a…

【监控】pushgateway中间服务组件

Pushgateway 是 Prometheus 生态中的一个中间服务组件&#xff0c;以独立工具形式存在&#xff0c;主要用于解决 Prometheus 无法直接获取监控指标的场景&#xff0c;弥补其定时拉取&#xff08;pull&#xff09;模式的不足。 其用途如下&#xff1a; 突破网络限制&#xff1…

打造AI智能旅行规划器:基于LLM和Crew AI的Agent实践

引言 今天来学习大佬开发的一个AI驱动的旅行规划应用程序&#xff0c;它能够自动处理旅行规划的复杂性——寻jni找航班、预订酒店以及优化行程。传统上&#xff0c;这个过程需要手动搜索多个平台&#xff0c;常常导致决策效率低下。 通过利用**代理型人工智能&#xff08;Age…

21. 自动化测试框架开发之Excel配置文件的测试用例改造

21. 自动化测试框架开发之Excel配置文件的测试用例改造 一、测试框架核心架构 1.1 组件依赖关系 # 核心库依赖 import unittest # 单元测试框架 import paramunittest # 参数化测试扩展 from chap3.po import * # 页面对象模型 from file_reader import E…

如何在电力系统中配置和管理SNTP时间同步?

在电力系统中配置和管理 SNTP 时间同步需结合行业标准&#xff08;如《DL/T 1100.1-2019》&#xff09;和分层架构特点&#xff0c;确保安全性、可靠性和精度适配。以下是具体操作指南&#xff0c;涵盖架构设计、设备配置、安全管理、运维监控四大核心环节&#xff0c;并附典型…

MTK-关于HW WCN的知识讲解

前言: 最近做项目过程中和硬件打交道比较多,现在关于整理下硬件的HW wcn的知识点 一 MTK常见的MT6631 Wi-Fi 2.4GHz 匹配调谐指南 ‌拓扑结构选择‌ 推荐采用并联电容拓扑(‌shunt cap topology‌)代替并联电感拓扑(‌shunt inductor topology‌),以减少潜在电路设计…

(1)课堂 1--5,这五节主要讲解 mysql 的概念,定义,下载安装与卸载

&#xff08;1&#xff09;谢谢老师&#xff1a; &#xff08;2&#xff09;安装 mysql &#xff1a; &#xff08;3&#xff09;镜像下载 &#xff0c;这个网址很好 &#xff1a; &#xff08;4&#xff09; 另一个虚拟机的是 zhang 123456 &#xff1a; 接着配置…

U-Boot ARMv8 平台异常处理机制解析

入口点&#xff1a;arch/arm/cpu/armv8/start.S 1. 判断是否定义了钩子&#xff0c;如有则执行&#xff0c;否则往下走。执行save_boot_params&#xff0c;本质就是保存一些寄存器的值。 2. 对齐修复位置无关码的偏移 假设U-Boot链接时基址为0x10000&#xff0c;但实际加载到0…

mysql安装教程--笔记

一、Windows 系统安装 方法1&#xff1a;使用 MySQL Installer&#xff08;推荐&#xff09; 1. 下载安装包 访问 MySQL 官网下载页面&#xff0c;选择 MySQL Installer for Windows。 2. 运行安装程序 双击下载的 .msi 文件&#xff0c;选择安装类型&#xff1a; ◦ Developer…

投资策略规划最优决策分析

目录 一、投资策略规划问题详细 二、存在最优投资策略&#xff1a;每年都将所有钱投入到单一投资产品中 &#xff08;一&#xff09;状态转移方程 &#xff08;二&#xff09;初始条件与最优策略 &#xff08;三&#xff09;证明最优策略总是将所有钱投入到单一投资产品中…

NGINX HTTP/3 实验指南安装、配置与调优

一、HTTP/3 简介 基于 QUIC&#xff1a;在 UDP 之上实现的多路复用传输&#xff0c;内置拥塞控制与前向纠错&#xff0c;无需三次握手即可恢复连接。零 RTT 重连&#xff1a;借助 TLS 1.3&#xff0c;实现连接恢复时的 0-RTT 数据发送&#xff08;视底层库支持&#xff09;。多…

编程日志5.28

string赋值操作 算法: #include<iostream> using namespace std; int main() { //1.字符串常量的赋值 string s1; s1 = "英雄哪里出来"; cout << s1 << endl; //2.字符串变量的赋值 string s2; s2 = s1; cout <…

AE的ai图层导到Ai

AE的ai图层导到ai 解决方法: 1、打开ai软件&#xff0c;不用新建&#xff0c;留在那就行。 2、在AE里选中任意一个ai文件图层&#xff0c;只需同时按住ctrl和英文字母键&#xff0c;图层就会自动全部导入到ai中 英文字母键的详情可以参考&#xff1a;http://www.yayihouse.co…

【Springboot+LangChain4j】Springboot项目集成LangChain4j(下)

前置条件&#xff1a;根据上篇文章完成springboot初步集成LangChain4j 【SpringbootLangChain4j】根据LangChain4j官方文档&#xff0c;三分钟完成Springboot项目集成LangChain4j&#xff08;上&#xff09;-CSDN博客 但是接口方法中&#xff0c;关于大模型的配置都是写死的&a…

好坏质检分类实战(异常数据检测、降维、KNN模型分类、混淆矩阵进行模型评估)

任务 好坏质检分类实战 task: 1、基于 data_class_raw.csv 数据&#xff0c;根据高斯分布概率密度函数&#xff0c;寻找异常点并剔除 2、基于 data_class_processed.csv 数据&#xff0c;进行 PCA 处理&#xff0c;确定重要数据维度及成分 3、完成数据分离&#xff0c;数据分离…

以少学习:通过无标签数据从大型语言模型进行知识蒸馏

Learning with Less: Knowledge Distillation from Large Language Models via Unlabeled Data 发表&#xff1a;NNACL-Findings 2025 机构&#xff1a;密歇根州立大学 Abstract 在实际的自然语言处理&#xff08;NLP&#xff09;应用中&#xff0c;大型语言模型&#xff08…