限流(Rate Limiting) 是一种通过限制系统在单位时间内处理的请求数量或资源使用量,防止系统因突发流量过载而崩溃的保护机制。

magic-spring-boot-starter-protection 是一个基于 Spring Boot 的防护组件,其 ratelimiter 模块提供了 声明式限流 功能,适用于防止恶意高频请求(如按钮疯狂点击、API 滥用等场景)。
限流组件的核心原理是 【AOP 拦截 ratelimiter注解】 + 【Redisson 限流器】 。
# 1 简单示例
示例代码:
@PostMapping("/create")
@Operation(summary = "创建 oneapi token") // Swagger/OpenAPI 文档描述
@PreAuthorize("@ss.hasPermission('ai:oneapitoken:create')") // Spring Security 权限校验
@RateLimiter(
count = 10, // 时间窗口内允许的最大请求数
timeUnit = TimeUnit.MINUTES // 时间窗口单位(分钟)
)
public CommonResult<Long> createOneApiToken(
@Valid @RequestBody AiOneApiTokenSaveReqVO saveReqVO // 自动校验请求体
) {
// 调用服务层方法并返回标准化响应
return success(oneApiTokenService.createOneApiToken(saveReqVO));
}
2
3
4
5
6
7
8
9
10
11
12
13
如上代码,每分钟最多可以执行 10 个 创建 apiToken 的请求。
疑问:如果想按照每个用户,或者每个 IP,限制请求呢?
可设置该注解的
keyResolver属性,可选择的有:
- DefaultRateLimiterKeyResolver:全局级别
- UserRateLimiterKeyResolver:用户 ID 级别
- ClientIpRateLimiterKeyResolver:用户 IP 级别
- ServerNodeRateLimiterKeyResolver:服务器 Node 级别
- ExpressionIdempotentKeyResolver:自定义级别,通过
keyArg属性指定 Spring EL 表达式
# 2 基本原理
通过 AOP 拦截器拦截带有注解 RateLimiter 的方法,然后通过 keyResolver 属性解析出 Key ,组装成 Redis Key 。
然后通过 Redisson 内置的限流组件,判断是否需要限流,若需要限流,则返回前端特定的 JSON 值。

# 3 Redisson 限流器
真正执行限流的是:

getRRateLimiter 的方法本质是调用 RedissonClient 的 RRateLimiter 限流器 API 。

Redisson 限流器的核心代码如下:
RRateLimiter rateLimiter = redissonClient.getRateLimiter("myRateLimiter");
// 初始化
// 最大流速 = 每1秒钟产生1个令牌
rateLimiter.trySetRate(RateType.OVERALL, 1, 1, RateIntervalUnit.SECONDS);
2
3
4
参数说明:
第一个参数是限流模式,RateLimiter.trySetRate 就是设置限流参数,RateType 有两种,OVERALL 是全局限流 ,PER_CLIENT 是单Client限流(可以认为就是单机限流)。
后面三个参数是指多长时间窗口内(参数 RateInterval + 参数 IntervalUnit ),限流总量不超过多少(参数 Rate)。
关于 Redisson 限流器基本原理 ,可以参考如下两篇文章:
https://juejin.cn/post/7199882882138898489
https://github.com/oneone1995/blog/issues/13
# 4 演示效果
当我们在用户列表添加如下限流注解时,刷新用户列表页面。
@RateLimiter(count = 2, time = 60)
接下来,观察 Redis GUI 界面:

1、Hash 存储限流器配置

Hash 数据存储了的工作模式(type)、限流数量(rate)、时间窗口大小(interval) 。
2、zset 存储当前所有的许可授权记录

zset 存储了当前所有的许可授权记录(含有许可授权时间戳),其中SCORE直接使用了时间戳,而 VALUE 中包含了 8 字节的随机值和许可的数量 。
3、String 存储当前可用的许可数量

