Skip to content

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] 配置驱动、中间件形态)。方法级精细限流见安全 → 限流

基于 Apache-2.0 许可证发布