Skip to content

梳理 ratelimit 模块设计问题与功能缺口 #3

Description

@zhoutaoo

背景

src/main/java/io/github/opensabre/sysadmin/ratelimit 模块做了一轮代码审查。当前实现更像第一版固定窗口计数器,但公共 API、配置和枚举已经扩展到多算法、多维度和全局规则,存在一些未接入或语义不一致的问题。

审查日期:2026-06-28

明确问题

  • 注解式限流可能未生效:SysadminApplication 未使用 @EnableRateLimitRateLimitAspect 只有 @Aspect 没有 @Component,切面大概率不会注册。
  • 全局开关未接入:ratelimit.enabled 只在配置类中存在,RateLimitAspectRateLimitServiceImpl 没有读取该开关。
  • 超限 HTTP 行为缺失:RateLimitExceededException 没有全局异常处理或 @ResponseStatus(429),REST 场景可能返回 500 而不是 429 Too Many Requests
  • keydimensions 语义冲突:注解中配置 key 后,RateLimitServiceImpl.generateKey 会直接忽略 dimensions,示例中的 IP + DEVICE + username 实际不会组合生效。
  • 超限结果缺少准确重置时间:RateLimitResult.denied 不设置 resetTime;允许请求时使用 now + period,没有使用 Redis TTL,响应头中的 reset 时间不准确。
  • resetLimit/getRemaining 接收原始 key,和内部统一 key prefix/build 规则不一致,调用方容易删错或查错 key。

过度设计或设计不合理

  • RateLimitAlgorithmType 暴露 SLIDING_WINDOWTOKEN_BUCKETLEAKY_BUCKET,但服务层全部 fallback 到 COUNTER,容易误导调用方。建议只暴露已实现算法,或对未实现算法直接抛配置错误。
  • RateLimitDimension 暴露 USERTENANT,但没有对应 extractor bean。建议补齐实现,或暂时移除未实现维度。
  • RateLimitProperties.globalratelimit-example.yml 中的 global 配置没有任何业务逻辑消费。建议实现全局规则或先删除示例,避免配置了但不生效。
  • RateLimitStorage 接口偏大,核心固定窗口只需要 incrementAndExpire/getCount/delete,当前通用 KV 能力会增加后续后端实现成本。
  • BusinessDimensionExtractor 文档说业务 key 由 SpEL 传入,但实现读取 X-Bid header,语义不一致。

建议优化

  • 明确启用方式:给 RateLimitAspect@Component,或在主应用加 @EnableRateLimit,保持一种主路径。
  • RateLimitAspectRateLimitServiceImpl 都尊重 ratelimit.enabled
  • 添加 RateLimitExceededException 全局异常处理,返回 429,并带 X-RateLimit-*Retry-After
  • 重新定义 key 生成规则:支持 key + dimensions 组合,或文档明确二者互斥。建议支持组合。
  • Redis Lua 返回 current + ttl,让 allowed/denied 都能得到准确 reset time。
  • maxCountperiodalgorithmdimensions 做启动期或调用期校验。
  • 将 fail-open/fail-closed 做成配置项,避免 Redis 故障时只能默认放行。

缺失功能点

  • 标准 429 响应与 Retry-After
  • 测试覆盖:当前 src/test/java/io/github/opensabre/sysadmin/ratelimit 只有 .DS_Store
  • 用户维度和租户维度实现。
  • 滑动窗口、令牌桶等算法,或明确不支持的失败策略。
  • endpoint/path/method 级别配置化限流。
  • 白名单/黑名单,例如内网 IP、管理员、健康检查跳过。
  • 指标观测:允许次数、拒绝次数、Redis 异常次数、fail-open 次数。
  • 管理或服务 API:按业务配置 reset、查询剩余次数、查询 TTL。

建议处理顺序

  1. 先修注解启用、全局开关、429 异常处理、key 生成语义和 Redis TTL。
  2. 补最小测试集:key 生成、固定窗口计数、AOP 注解、超限响应。
  3. 收敛未实现的算法/维度/配置面,避免对外暴露未完成能力。
  4. 再扩用户/租户维度、endpoint 配置、观测指标和高级算法。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions