-- request_rate_limiter.{id}.tokens local tokens_key = KEYS[1]
-- request_rate_limiter.{id}.timestamp local timestamp_key = KEYS[2]
-- 令牌桶每秒填充平均速率 local rate = tonumber(ARGV[1]) -- 令牌桶最大容量 local capacity = tonumber(ARGV[2]) -- 秒级时间戳 local now = tonumber(ARGV[3]) -- 1 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)) -- 若桶为空, 说明在令牌桶的过期时间内没有请求,因此将桶中的令牌填满 if last_tokens == nilthen last_tokens = capacity end
-- 上一次请求的时间戳 local last_refreshed = tonumber(redis.call("get", timestamp_key)) -- 如果上一次请求的时间戳为nil,则说明此次请求为第一次请求或者上次请求间隔过久导致令牌桶过期 if last_refreshed == nilthen last_refreshed = 0 end
-- 与上一次请求的时间差 local delta = math.max(0, now-last_refreshed)
-- 如果填充后令牌数量还是小于1,则说明该请求被限流,拦截 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