SpringGateway - Redis限流元件之Luau指令碼&Java實現
在Spring Cloud Gateway中,限流作為閘道器最基本的功能,Spring Cloud Gateway官方就提供了RequestRateLimiterGatewayFilterFactory這個類,適用Redis和lua指令碼實現了令牌桶的方式。
具體實現邏輯在RequestRateLimiterGatewayFilterFactory類中,預設呼叫引數如下:
List<String> keys = getKeys(id);
// The arguments to the LUA script. time() returns unixtime in seconds.
List<String> scriptArgs = Arrays.asList(replenishRate + "", burstCapacity + "",
Instant.now().getEpochSecond() + "", "1");
// allowed, tokens_left = redis.eval(SCRIPT, keys, args)
Flux<List<Long>> flux = this.redisTemplate.execute(this.script, keys, scriptArgs);
static List<String> getKeys(String id) {
// use `{}` around keys to use Redis Key hash tags
// this allows for using redis cluster
// Make a unique key per user.
String prefix = "request_rate_limiter.{" + id;
// You need two Redis keys for Token Bucket.
String tokenKey = prefix + "}.tokens";
String timestampKey = prefix + "}.timestamp";
return Arrays.asList(tokenKey, timestampKey);
}
lua指令碼在Scripts資料夾下:request_rate_limitter.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/rate
local 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 = capacity
end
--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 = 0
end
--redis.log(redis.LOG_WARNING, "last_refreshed " .. last_refreshed)
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
local allowed_num = 0
if allowed then
new_tokens = filled_tokens - requested
allowed_num = 1
end
--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 }
相關文章
- redis+lua指令碼實現介面限流Redis指令碼
- 如何使用 redis 實現限流Redis
- Java Redis多限流JavaRedis
- 基於 Redis 實現分散式應用限流Redis分散式
- 【分散式架構】(10)---基於Redis元件的特性,實現一個分散式限流分散式架構Redis元件
- Redis使用lua指令碼實現庫存扣減Redis指令碼
- redis+lua實現指令碼一鍵查詢Redis指令碼
- redis實際應用-限流Redis
- 使用 Redis 實現限流——滑動視窗演算法Redis演算法
- Java併發:分散式應用限流 Redis + Lua 實踐Java分散式Redis
- redis執行lua指令碼的實現方法括饃Redis指令碼
- 為什麼在 Redis 實現 Lua 指令碼事務?Redis指令碼
- redis命令之-script指令碼學習Redis指令碼
- Envoy實現.NET架構的閘道器(五)整合Redis實現限流架構Redis
- 從kratos分析BBR限流原始碼實現原始碼
- 使用Java實現一個JS指令碼引擎JavaJS指令碼
- 基於redis實現的四種常見的限流策略Redis
- Java常用中介軟體之 NGINX實現限流功能的官方文件說明JavaNginx
- flyway實現java 自動升級SQL指令碼JavaSQL指令碼
- 新姿勢!Redis中呼叫Lua指令碼以實現原子性操作Redis指令碼
- Redis - Lua 指令碼Redis指令碼
- Redis的指令碼Redis指令碼
- Redis 應用-限流Redis
- Locust 程式碼指令碼實現指令碼
- React原始碼之元件的實現與首次渲染React原始碼元件
- Java指令碼實現在微信聊天框發訊息Java指令碼
- Redis學習筆記(三)使用Lua指令碼實現分散式鎖Redis筆記指令碼分散式
- Redis 實戰 —— 14. Redis 的 Lua 指令碼程式設計Redis指令碼程式設計
- 微服務元件之限流器與熔斷器微服務元件
- ETL工具與指令碼實現之間的對比指令碼
- 基於Redis實現一套支援排隊等待的限流器Redis
- ETL指令碼的實現指令碼
- 專案如何實現限流?
- redis分散式鎖-java實現Redis分散式Java
- Redis使用Lua指令碼Redis指令碼
- redis重啟指令碼Redis指令碼
- 分散式鎖之Redis實現分散式Redis
- 使用Redis進行限流Redis