如何理解spring-cloud-gateway自带redis限流脚本
发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这篇文章主要讲解了"如何理解spring-cloud-gateway自带redis限流脚本",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何理解spr
千家信息网最后更新 2026年10月31日如何理解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安全错误
数据库的锁怎样保障安全
互联网黑科技
互联网医疗科技
浩特互联网科技
安徽鑫晟辉互联网科技
米客互联网科技
奔汉互联网科技
美国互联网前沿科技
无锡溥仪互联网科技有限公司
中国互联网有什么科技含量
央行互联网金融科技公司
互联网公司科技股
上海宁丞科技互联网
宝灵互联网科技有限公司
花神(南京)互联网科技有限公司
杭州壁岐互联网科技有限公司
互联网媒体平台算高科技产业
长沙互联网科技
怎样加入科技互联网
中国科技和美国互联网
盐城市攀科互联网科技有限公司
手冲咖啡和咖啡机区别
未来的互联网科技
互联网科技生活的内容
央行互联网金融科技公司
互联网和黑科技的看法
上海创道互联网络科技有限公司
35岁以上互联网科技行业
江苏互联网智能科技产品出厂价
美国五大互联网科技公司市值多少
互联网金融金融科技