Redis 分布式限流
ace-security 的限流组件默认用进程内计数——多实例部署时每个实例各有一份窗口,整体放行量随实例数翻倍。把存储切到 Redis 后所有实例共享同一限流窗口。
开启
toml
[ratelimit]
enabled = true
max = 100 # 窗口内最大请求数
windowMs = 60000 # 窗口长度(毫秒)
store = "redis" # 默认 "memory";切 Redis 只改这一行
key = "global" # 计数键(前缀 ace:rl:);默认全局一个窗口前提:应用已引入并 import ace_redis(Redis 组件装配顺序先于限流组件,由组件依赖关系自动保证)。
行为
算法:固定窗口计数——
INCR ace:rl:<key>:<窗口序号>,窗口首个请求同时PEXPIRE整窗过期(键自清理);计数超过max返回429。回退:
store指定的后端未注册(如没引入 ace-redis)时打印日志并回退进程内限流,服务照常可用:ACE ratelimit: store 'redis' not registered, fallback to in-memory rate limit故障语义 fail-open:限流计数期间 Redis 异常时放行并打日志——缓存设施故障不应放大为全站 429 拒绝服务。
自定义限流后端
限流存储与缓存一样是命名后端抽象(ace_framework_runtime),可注册自己的实现:
cangjie
public interface RateLimitStore {
// 返回 true 放行,false 拒绝(429)
func tryAcquire(key: String, maxRequests: Int64, windowMs: Int64): Bool
}
registerRateLimitStore("my-store", {=> MyStore()}) // [ratelimit] store = "my-store"与 @RateLimit 宏的关系
本篇是组件级全局限流([ratelimit] 配置驱动、中间件形态)。方法级精细限流见安全 → 限流。