接口限流
youlai-boot 提供基于 IP 的全局限流机制,通过过滤器实现接口级别的并发控制。
限流方式
| 方式 | 实现位置 | 说明 |
|---|---|---|
| IP 全局限流 | RateLimiterFilter | 基于令牌桶算法,全局限流所有接口 |
实现原理
过滤器链
限流过滤器位于 Spring Security 过滤器链前端:
Redis Key 设计
Key: rate_limiter:ip:{ip}
Value: 请求计数
TTL: 1 秒示例:
rate_limiter:ip:192.168.1.100核心算法
令牌桶算法:
- 每个 IP 在 1 秒时间窗口内统计请求次数
- 首次访问时设置 Key,过期时间 1 秒
- 每次请求自增计数
- 计数超出阈值时触发限流
核心代码:
java
public boolean rateLimit(String ip) {
String key = StrUtil.format(RedisConstants.RateLimiter.IP, ip);
// 自增请求计数
Long count = redisTemplate.opsForValue().increment(key);
if (count == null || count == 1) {
// 第一次访问时设置过期时间为 1 秒
redisTemplate.expire(key, 1, TimeUnit.SECONDS);
}
// 获取系统配置的限流阈值
Object systemConfig = configService.getSystemConfig(
SystemConstants.SYSTEM_CONFIG_IP_QPS_LIMIT_KEY
);
if (systemConfig == null) {
return false; // 未配置则跳过限流
}
long limit = Convert.toLong(systemConfig, DEFAULT_IP_LIMIT);
return count != null && count > limit;
}配置说明
限流阈值配置
通过系统配置管理限流阈值:
配置 Key:IP_QPS_THRESHOLD_LIMIT
配置方式:
在系统管理 → 系统配置中添加:
| 配置键 | 配置值 | 说明 |
|---|---|---|
IP_QPS_THRESHOLD_LIMIT | 10 | 单 IP 每秒最大请求数 |
默认值:
- 未配置时:跳过限流
- 配置为空时:默认 10 次/秒
过滤器注册
在 SecurityConfig 中注册:
java
.addFilterBefore(
new RateLimiterFilter(redisTemplate, configService),
UsernamePasswordAuthenticationFilter.class
)过滤器位置:在用户名密码认证过滤器之前执行。
错误响应
当触发限流时,返回以下响应:
json
{
"code": "A0502",
"msg": "请求并发数超出限制",
"data": null
}错误码说明:
| 错误码 | HTTP 状态码 | 说明 |
|---|---|---|
A0502 | 429 | 请求并发数超出限制 |
应用场景
全局防护
适用于所有接口的全局限流:
- 防止恶意请求攻击
- 保护系统资源
- 限制爬虫抓取
典型场景
| 场景 | 建议阈值 | 说明 |
|---|---|---|
| 普通应用 | 10-50 次/秒 | 正常业务流量 |
| 高并发应用 | 100-500 次/秒 | 促销、活动场景 |
| API 网关 | 1000+ 次/秒 | 大流量入口 |
与其他限流方案对比
| 方案 | 实现方式 | 优势 | 劣势 |
|---|---|---|---|
| IP 全局限流(当前) | Redis + Filter | 实现简单、全局生效 | 粒度较粗 |
| 接口级限流 | 注解 + AOP | 精确控制每个接口 | 配置繁琐 |
| 用户级限流 | 用户 ID + Redis | 防止单用户滥用 | 需要登录态 |
| 分布式限流 | Redis + Lua | 集群环境精确控制 | 实现复杂 |
扩展建议
1. 接口级限流
参考 Django 版本的装饰器方式,实现接口级限流:
java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RateLimit {
int value() default 60; // 限流时间(秒)
String message() default "操作频繁,请稍后再试";
}使用示例:
java
@PostMapping("/sms/code")
@RateLimit(value = 60)
public Result<?> sendSmsCode(@RequestParam String mobile) {
// 发送短信验证码
}2. 多维度限流
扩展为多维度限流:
java
public enum RateLimitType {
IP, // IP 限流
USER, // 用户限流
GLOBAL // 全局限流
}3. 动态配置
支持接口级动态配置:
java
@RateLimit(key = "sms_code", fallbackValue = 60)
public Result<?> sendSmsCode() {
// 从配置中心读取限流时间
}相关文件
| 文件 | 说明 |
|---|---|
core/filter/RateLimiterFilter.java | IP 限流过滤器 |
config/SecurityConfig.java | 过滤器注册配置 |
common/constant/RedisConstants.java | Redis Key 常量 |
common/constant/SystemConstants.java | 系统配置常量 |
core/web/ResultCode.java | 错误码定义 |
