如何理解spring-cloud-gateway自带redis限流脚本
发表于:2025-11-07 作者:千家信息网编辑
千家信息网最后更新 2025年11月07日,这篇文章主要讲解了"如何理解spring-cloud-gateway自带redis限流脚本",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何理解spr
千家信息网最后更新 2025年11月07日如何理解spring-cloud-gateway自带redis限流脚本
这篇文章主要讲解了"如何理解spring-cloud-gateway自带redis限流脚本",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何理解spring-cloud-gateway自带redis限流脚本"吧!
filter入口: org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory#apply
限流判断入口: org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter#isAllowed
@Override @SuppressWarnings("unchecked") public Mono isAllowed(String routeId, String id) { if (!this.initialized.get()) { throw new IllegalStateException("RedisRateLimiter is not initialized"); } Config routeConfig = loadConfiguration(routeId); // How many requests per second do you want a user to be allowed to do? int replenishRate = routeConfig.getReplenishRate(); // How much bursting do you want to allow? int burstCapacity = routeConfig.getBurstCapacity(); try { List keys = getKeys(id); // The arguments to the LUA script. time() returns unixtime in seconds. List scriptArgs = Arrays.asList(replenishRate + "", burstCapacity + "", Instant.now().getEpochSecond() + "", "1"); // allowed, tokens_left = redis.eval(SCRIPT, keys, args) Flux> flux = this.redisTemplate.execute(this.script, keys, scriptArgs); // .log("redisratelimiter", Level.FINER); return flux.onErrorResume(throwable -> Flux.just(Arrays.asList(1L, -1L))) .reduce(new ArrayList(), (longs, l) -> { longs.addAll(l); return longs; }).map(results -> { boolean allowed = results.get(0) == 1L; Long tokensLeft = results.get(1); Response response = new Response(allowed, getHeaders(routeConfig, tokensLeft)); if (log.isDebugEnabled()) { log.debug("response: " + response); } return response; }); } catch (Exception e) { /* * We don't want a hard dependency on Redis to allow traffic. Make sure to set * an alert so you know if this is happening too much. Stripe's observed * failure rate is 0.01%. */ log.error("Error determining if user allowed from redis", e); } return Mono.just(new Response(true, getHeaders(routeConfig, -1L))); }
lua脚本加载入口: org.springframework.cloud.gateway.config.GatewayRedisAutoConfiguration#redisRequestRateLimiterScript
@Bean @SuppressWarnings("unchecked") public RedisScript redisRequestRateLimiterScript() { DefaultRedisScript redisScript = new DefaultRedisScript<>(); redisScript.setScriptSource(new ResourceScriptSource( new ClassPathResource("META-INF/scripts/request_rate_limiter.lua"))); redisScript.setResultType(List.class); return redisScript; }request_rate_limiter.lua脚本
local tokens_key = KEYS[1]local timestamp_key = KEYS[2]--redis.log(redis.LOG_WARNING, "tokens_key " .. tokens_key)local rate = tonumber(ARGV[1])local capacity = tonumber(ARGV[2])local now = tonumber(ARGV[3])local requested = tonumber(ARGV[4])local fill_time = capacity/ratelocal ttl = math.floor(fill_time*2)--redis.log(redis.LOG_WARNING, "rate " .. ARGV[1])--redis.log(redis.LOG_WARNING, "capacity " .. ARGV[2])--redis.log(redis.LOG_WARNING, "now " .. ARGV[3])--redis.log(redis.LOG_WARNING, "requested " .. ARGV[4])--redis.log(redis.LOG_WARNING, "filltime " .. fill_time)--redis.log(redis.LOG_WARNING, "ttl " .. ttl)local last_tokens = tonumber(redis.call("get", tokens_key))if last_tokens == nil then last_tokens = capacityend--redis.log(redis.LOG_WARNING, "last_tokens " .. last_tokens)local last_refreshed = tonumber(redis.call("get", timestamp_key))if last_refreshed == nil then last_refreshed = 0end--redis.log(redis.LOG_WARNING, "last_refreshed " .. last_refreshed)local delta = math.max(0, now-last_refreshed)--重点是这里,rate是相对于capacity而言,如果大于等于capacity,那么每秒的并发量就是capacity,--如果小于capacity,那么才会每秒固定添加rate个令牌到桶中。--正常限流建议设置小于capacity,否则当capacity瞬间用完,这个时候说明已经达到了系统最大并发阀值,--下一秒瞬间又恢复最大令牌桶阀值,速率过大反而起不到限流作用。local filled_tokens = math.min(capacity, last_tokens+(delta*rate))local allowed = filled_tokens >= requestedlocal new_tokens = filled_tokenslocal allowed_num = 0if allowed then new_tokens = filled_tokens - requested allowed_num = 1end--redis.log(redis.LOG_WARNING, "delta " .. delta)--redis.log(redis.LOG_WARNING, "filled_tokens " .. filled_tokens)--redis.log(redis.LOG_WARNING, "allowed_num " .. allowed_num)--redis.log(redis.LOG_WARNING, "new_tokens " .. new_tokens)redis.call("setex", tokens_key, ttl, new_tokens)redis.call("setex", timestamp_key, ttl, now)return { allowed_num, new_tokens }感谢各位的阅读,以上就是"如何理解spring-cloud-gateway自带redis限流脚本"的内容了,经过本文的学习后,相信大家对如何理解spring-cloud-gateway自带redis限流脚本这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!
脚本
入口
学习
最大
令牌
内容
就是
作用
建议
思路
情况
文章
时候
更多
知识
知识点
篇文章
系统
跟着
速率
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
国家的网络安全学校
江苏弹性云服务器
网络安全大赛郑州什么地方
网络安全的单选题
chip数据库
35岁学网络技术
超云服务器ipmi管理口地址
服务器柜三维图
成都即时通讯软件开发
深信服网络安全态势感知方案
质谱数据库免费
国计民生网络安全
电子信息通信网络安全工程师
造价数据库软件开发
英国的网络安全产业
软件开发网站学习班
可视化网络安全感知系统
数据库损坏了
炎帝服务器安全吗
海阳市软件开发学习
高青生产软件开发公司
什么是数据库的安全分析
dns中继服务器
建业新生活服务器Ip地址
成都银行软件开发岗位
百度软件开发工程师照片
西藏优质软件开发报价
java排序页面数据库
国家网络安全等级认证证书
万方数据库 账号