kindergarten_java/docs/限流功能使用说明.md
En 0d4275b235 feat: 完善 OpenAPI 注解和前端 API 客户端
主要变更:
1. 所有 Entity/DTO/VO 添加 @Schema 注解,完善 API 文档
2. 新增前端 API 封装模块 (src/apis),包含 fetch.ts 和 apis.ts
3. 生成完整的 TypeScript 类型定义(100+ 个模型)
4. pom.xml 添加 Maven 编译配置和 UTF-8 编码支持
5. 更新 CLAUDE.md 开发文档,新增接口规范和 Swagger 注解规范
6. 清理旧的文档文件和 Flyway 迁移脚本

技术细节:
- 后端:27 个实体类 + 所有 DTO/Response 添加 Swagger 注解
- 前端:新增 orval 生成的 API 客户端类型
- 构建:配置 Maven compiler plugin 和 Spring Boot 插件的 JVM 参数
- 数据库:新增 schema 导出文件,删除旧 Flyway 迁移脚本

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 23:51:02 +08:00

6.4 KiB
Raw Blame History

限流功能使用说明

功能概述

本项目已集成基于 Redis 滑动窗口算法的限流功能,支持两种使用方式:

  1. 配置化限流 - 在 application.yml 中配置规则,自动对所有接口生效
  2. 注解限流 - 在 Controller 方法上使用 @RateLimit 注解,针对特定接口限流

技术实现

核心组件

组件 说明
@RateLimit 限流注解,可自定义时间窗口、最大请求数
RateLimitProperties 配置化限流的属性类
RateLimiter Redis 限流工具类(滑动窗口算法)
RateLimitAspect 注解限流的 AOP 切面
RateLimitInterceptor 配置化限流的拦截器
ErrorCode.RATE_LIMIT_EXCEEDED 限流错误码5001

限流优先级

注解限流 > 配置化限流 > 默认限流

使用方式

方式一:配置化限流(推荐作为基础防护)

application.yml 中配置:

rate-limit:
  enabled: true                      # 是否启用限流
  default-time-window: 60            # 默认时间窗口(秒)
  default-max-requests: 1000         # 默认时间窗口内最大请求数
  rules:                             # 限流规则列表
    # 登录接口限流 - 防止暴力破解
    - pattern: "/api/v1/auth/login"
      time-window: 60
      max-requests: 10
    # 验证码接口限流 - 防止刷验证码
    - pattern: "/api/v1/auth/captcha"
      time-window: 60
      max-requests: 5
    # 短信接口限流 - 防止短信轰炸
    - pattern: "/api/v1/sms/**"
      time-window: 60
      max-requests: 3
    # 文件上传接口限流
    - pattern: "/api/v1/**/upload/**"
      time-window: 60
      max-requests: 30
  exclude-patterns:                  # 排除限流的接口
    - "/doc.html"
    - "/swagger-resources/**"
    - "/v3/api-docs/**"
    - "/webjars/**"
    - "/uploads/**"

方式二:注解限流(针对特殊接口)

在 Controller 方法上添加 @RateLimit 注解:

package com.reading.platform.controller.auth;

import com.reading.platform.common.annotation.RateLimit;
import com.reading.platform.common.response.Result;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/v1/auth")
public class AuthController {

    /**
     * 登录接口 - 限流防止暴力破解
     * 60 秒内最多 10 次请求
     */
    @PostMapping("/login")
    @RateLimit(time = 60, maxRequests = 10, message = "登录过于频繁,请稍后再试")
    public Result<LoginResponse> login(@RequestBody LoginRequest request) {
        // ... 登录逻辑
    }

    /**
     * 发送短信验证码 - 严格限流
     * 60 秒内最多 3 次请求
     */
    @PostMapping("/captcha")
    @RateLimit(time = 60, maxRequests = 3, message = "操作过于频繁,请稍后再试")
    public Result<Void> sendCaptcha(@RequestParam String phone) {
        // ... 发送验证码逻辑
    }

    /**
     * 自定义限流键前缀
     * 适用于需要按用户 ID 等特殊维度限流的场景
     */
    @PostMapping("/special")
    @RateLimit(keyPrefix = "special_api:", time = 60, maxRequests = 5)
    public Result<Void> specialApi() {
        // ... 特殊接口逻辑
    }
}

常见限流场景建议值

接口类型 时间窗口 最大请求数 说明
登录接口 60 秒 10 防止暴力破解
验证码/短信 60 秒 3-5 防止短信轰炸
文件上传 60 秒 30 防止资源滥用
普通业务接口 60 秒 100-1000 根据业务调整
导出接口 60 秒 5-10 防止服务器过载

限流响应

当请求被限流拦截时,返回:

配置化限流响应:

{
  "code": 5001,
  "message": "请求过于频繁,请稍后再试",
  "data": null
}

HTTP 状态码:429 Too Many Requests

响应头:

X-RateLimit-Limit: 1
X-RateLimit-Remaining: 0
Retry-After: 60

注解限流响应:

{
  "code": 5001,
  "message": "登录过于频繁,请稍后再试",
  "data": null
}

Redis 数据结构

限流使用 Redis 的 Sorted Set(有序集合)存储:

  • Key 格式: rate_limit:{key}
  • Member: 时间戳(毫秒)
  • Score: 时间戳(毫秒)

示例:

rate_limit:192.168.1.1:/api/v1/auth/login
  |- 1710000000000
  |- 1710000001000
  |- 1710000002000

注意事项

  1. Redis 依赖: 限流功能依赖 Redis需确保 Redis 服务可用
  2. 异常情况放行: 当 Redis 不可用时,系统会自动放行请求,避免影响正常业务
  3. 集群部署: 滑动窗口算法天然支持分布式,无需额外配置
  4. 监控告警: 建议添加限流触发的监控告警,及时发现异常流量

日志示例

2024-03-10 22:00:00 WARN  - 请求被限流拦截URI=/api/v1/auth/login, 规则=/api/v1/auth/login, 最大请求数=10
2024-03-10 22:00:01 DEBUG - 请求通过限流检查URI=/api/v1/users, 规则=default

测试方法

使用 curl 或 Postman 快速测试:

# 循环发送 15 次登录请求(第 11 次开始应该被限流)
for i in {1..15}; do
  echo "请求 $i:"
  curl -X POST http://localhost:8080/api/v1/auth/login \
    -H "Content-Type: application/json" \
    -d '{"username":"test","password":"test"}' \
    -w "\nHTTP 状态码:%{http_code}\n\n"
done

配置说明

RateLimit 注解参数

参数 类型 默认值 说明
keyPrefix String "" 限流键前缀,默认使用 IP:类名。方法名
time long 60 时间窗口大小
timeUnit TimeUnit SECONDS 时间单位
maxRequests long 100 时间窗口内最大请求数
message String "请求过于频繁,请稍后再试" 限流提示信息
enabled boolean true 是否启用限流

application.yml 配置参数

参数 类型 默认值 说明
enabled boolean true 是否启用限流
default-time-window long 60 默认时间窗口(秒)
default-max-requests long 1000 默认最大请求数
rules List [] 限流规则列表
exclude-patterns List [] 排除限流的接口路径

RateLimitRule 配置参数

参数 类型 说明
pattern String 接口路径(支持 Ant 风格通配符)
time-window long 时间窗口(秒)
max-requests long 最大请求数