# 限流功能使用说明 ## 功能概述 本项目已集成基于 Redis 滑动窗口算法的限流功能,支持两种使用方式: 1. **配置化限流** - 在 `application.yml` 中配置规则,自动对所有接口生效 2. **注解限流** - 在 Controller 方法上使用 `@RateLimit` 注解,针对特定接口限流 ## 技术实现 ### 核心组件 | 组件 | 说明 | |------|------| | `@RateLimit` | 限流注解,可自定义时间窗口、最大请求数 | | `RateLimitProperties` | 配置化限流的属性类 | | `RateLimiter` | Redis 限流工具类(滑动窗口算法) | | `RateLimitAspect` | 注解限流的 AOP 切面 | | `RateLimitInterceptor` | 配置化限流的拦截器 | | `ErrorCode.RATE_LIMIT_EXCEEDED` | 限流错误码(5001) | ### 限流优先级 **注解限流 > 配置化限流 > 默认限流** ## 使用方式 ### 方式一:配置化限流(推荐作为基础防护) 在 `application.yml` 中配置: ```yaml 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` 注解: ```java 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 login(@RequestBody LoginRequest request) { // ... 登录逻辑 } /** * 发送短信验证码 - 严格限流 * 60 秒内最多 3 次请求 */ @PostMapping("/captcha") @RateLimit(time = 60, maxRequests = 3, message = "操作过于频繁,请稍后再试") public Result sendCaptcha(@RequestParam String phone) { // ... 发送验证码逻辑 } /** * 自定义限流键前缀 * 适用于需要按用户 ID 等特殊维度限流的场景 */ @PostMapping("/special") @RateLimit(keyPrefix = "special_api:", time = 60, maxRequests = 5) public Result specialApi() { // ... 特殊接口逻辑 } } ``` ## 常见限流场景建议值 | 接口类型 | 时间窗口 | 最大请求数 | 说明 | |---------|---------|-----------|------| | 登录接口 | 60 秒 | 10 | 防止暴力破解 | | 验证码/短信 | 60 秒 | 3-5 | 防止短信轰炸 | | 文件上传 | 60 秒 | 30 | 防止资源滥用 | | 普通业务接口 | 60 秒 | 100-1000 | 根据业务调整 | | 导出接口 | 60 秒 | 5-10 | 防止服务器过载 | ## 限流响应 当请求被限流拦截时,返回: **配置化限流响应:** ```json { "code": 5001, "message": "请求过于频繁,请稍后再试", "data": null } ``` HTTP 状态码:`429 Too Many Requests` 响应头: ``` X-RateLimit-Limit: 1 X-RateLimit-Remaining: 0 Retry-After: 60 ``` **注解限流响应:** ```json { "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 快速测试: ```bash # 循环发送 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 | 最大请求数 |