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 配置、观测指标和高级算法。

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions