1.6 KiB
1.6 KiB
令牌桶 — Redis Lua 脚本
原子操作,单次 Redis 往返
local data = redis.call('HMGET', key, 'tokens', 'ts')
local tokens = tonumber(data[1])
local last_ts = tonumber(data[2])
-- 首次访问,初始化满桶
if tokens == nil then
tokens = burst
last_ts = now
end
-- 计算时间差,补充令牌
local delta = now - last_ts
if delta > 0 then
local refill = (delta * rate) / 1000
tokens = math.min(burst, tokens + refill)
end
限流中间件集成
Gin 中间件 + 统一错误格式
`func RateLimit(limiter Limiter, keyFunc func(c *gin.Context) string) gin.HandlerFunc` — 可配置的 key 提取函数,支持按用户ID、IP、端点等维度限流。- 用户级:auth 路由组,key = userID,保护个人配额
- 全局级:
/generate端点,key = endpoint,保护总容量
- 通过:设置
X-RateLimit-Remaining头 - 拒绝:HTTP 429 +
Retry-After头 + 统一 JSON 错误体