限流(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));
}
1
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 限流器

真正执行限流的是:

tryAcquire

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

Redisson 限流器的核心代码如下:

RRateLimiter rateLimiter = redissonClient.getRateLimiter("myRateLimiter");
// 初始化
// 最大流速 = 每1秒钟产生1个令牌
rateLimiter.trySetRate(RateType.OVERALL, 1, 1, RateIntervalUnit.SECONDS);
1
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)
1

接下来,观察 Redis GUI 界面:

1、Hash 存储限流器配置

Hash 数据存储了的工作模式(type)、限流数量(rate)、时间窗口大小(interval) 。

2、zset 存储当前所有的许可授权记录

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

3、String 存储当前可用的许可数量

上次更新: 2026/6/28