SpringBoot 分布式令牌桶限流:集成 Bucket4j + Redis
SpringBoot 分布式令牌桶限流:集成 Bucket4j + Redis
一、pom.xml
SpringBoot 3+ 和 JDK 17+
本文使用的 SpringBoot 版本为 4.0.3,JDK 版本为 25,以下是集成 Bucket4j 需要引入的相关依赖:
<!-- springboot相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aspectj</artifactId>
</dependency>
<!-- bucket4j的springboot依赖 -->
<dependency>
<groupId>com.giffing.bucket4j.spring.boot.starter</groupId>
<artifactId>bucket4j-spring-boot-starter</artifactId>
<version>0.14.0</version>
</dependency>
<!-- bucket4j的redis-jedis依赖 -->
<dependency>
<groupId>com.bucket4j</groupId>
<artifactId>bucket4j_jdk17-redis-common</artifactId>
<version>8.15.0</version>
</dependency>
<dependency>
<groupId>com.bucket4j</groupId>
<artifactId>bucket4j_jdk17-jedis</artifactId>
<version>8.15.0</version>
</dependency>
<!-- spring-boot-starter-cache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- jedis依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
bucket4j-spring-boot-starter 以及 bucket4j_jdk17-redis-common、bucket4j_jdk17-jedis 的版本号参考 bucket4j-spring-boot-starter github 文档:

SpringBoot 2 和 JDK 8
使用 SpringBoot 2 和 JDK 8 时,应调整为:
<!-- bucket4j的springboot依赖 -->
<dependency>
<groupId>com.giffing.bucket4j.spring.boot.starter</groupId>
<artifactId>bucket4j-spring-boot-starter</artifactId>
<version>0.8.1</version>
</dependency>
<!-- bucket4j的redis-jedis依赖 -->
<dependency>
<groupId>com.bucket4j</groupId>
<artifactId>bucket4j_jdk8-redis</artifactId>
<version>8.1.0</version>
</dependency>
<!-- jedis依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
需要注意的是,JDK 8 无法使用 @RateLimiting 。
Redis 客户端选择
大部分 SpringBoot 应用使用的是 spring-boot-starter-web 依赖,基于 Servlet 同步阻塞模型,因此在集成 Bucket4j 时,必须使用 Jedis 客户端。如果使用的是基于 Flux 异步响应模型的 spring-boot-starter-webflux 依赖,则可以选择 Lettuce 或 Redisson 客户端。
可以查看 bucket4j-spring-boot-starter 的自动配置源码,Jedis 只在检测到 Servlet 时自动配置,Lettuce 和 Redisson 只在 WebFlux 或 GateWay 时自动配置。
二、Bucket4j 配置
方式一:注解 @RateLimiting
yaml 配置:
bucket4j:
cache-to-use: redis-jedis
methods:
- name: bucket4jMethod #@RateLimiting引用的方法名
cache-name: buckets
rate-limit:
bandwidths:
- capacity: 5 #总容量
refill-capacity: 3 #填充量
time: 10 #10s内填充3个令牌,最多保留5个
unit: seconds
refill-speed: greedy #greedy贪婪模式:在时间内均匀发放,interval间隔模式:到时间一次性发放
将 @RateLimiting 注解在需要限流的 Controller 层方法上:
@RateLimiting(name = "bucket4jMethod", //配置的methods名称
fallbackMethodName = "fallbackMethod") //超限时执行的方法名,定义在下面
@PostMapping("/rateLimitTest")
public ResponseEntity<Boolean> rateLimitTest() {
return ResponseEntity.ok(true);
}
/**
* 定义当bucket4j请求超限时执行的后备方法,后备方法的签名必须与原方法保持一致
*/
public ResponseEntity<Boolean> fallbackMethod() {
return ResponseEntity.ok(false);
}
方式二:配置 filters
bucket4j:
cache-to-use: redis-jedis
filters:
- cache-name: buckets
url: /test/rateLimitTest #用正则表达式匹配需要限流的url
http-content-type: 'application/json;charset=UTF-8'
http-status-code: TOO_MANY_REQUESTS
http-response-body: '{ "code": "429", "message": "当前请求人数过多,请稍后再试" }' #超限时返回的响应体
rate-limits:
- bandwidths:
- capacity: 3
refill-capacity: 1
time: 5
unit: seconds
refill-speed: greedy
三、JedisPool 配置
完成上面的配置后,初次启动报错。检查 Bucket4j 的 Jedis 源码发现需要定义一个 JedisPool 的 Bean:

编写 JedisPool 配置类:
@Configuration
public class RedisConfig {
/**
* 用于bucket4j
*/
@Bean
public JedisPool jedisPool(JedisProperties jedisProperties) {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(jedisProperties.getJedis().getPool().getMaxActive());
jedisPoolConfig.setMaxWait(jedisProperties.getJedis().getPool().getMaxWait());
jedisPoolConfig.setMaxIdle(jedisProperties.getJedis().getPool().getMaxIdle());
jedisPoolConfig.setMinIdle(jedisProperties.getJedis().getPool().getMinIdle());
return new JedisPool(
jedisPoolConfig,
jedisProperties.getHost(),
jedisProperties.getPort(),
Math.toIntExact(jedisProperties.getTimeout().toMillis()),
jedisProperties.getPassword(),
jedisProperties.getDatabase());
}
}
读取 Jedis 配置的类:
@Component
@ConfigurationProperties(prefix = "spring.data.redis")
@Data
public class JedisProperties {
private String host;
private Integer port;
private String password;
private Integer database;
private Duration timeout;
private MyJedisPool jedis;
@Data
public static class MyJedisPool {
private Pool pool;
@Data
public static class Pool {
private Integer maxActive;
private Duration maxWait;
private Integer maxIdle;
private Integer minIdle;
}
}
}
application.yaml:
spring:
data:
redis:
host: ${host}
port: 6379
password: ${password}
database: 0
timeout: 10s
#用于bucket4j
jedis:
pool:
max-active: 200
max-wait: 10s
max-idle: 10
min-idle: 1
至此已完成所有配置,可以请求方法进行限流测试了。
参考:
[1]: bucket4j github 文档
[2]: bucket4j-spring-boot-starter github 文档
[3]: bucket4j 官方文档:集成 jedis
[4]: 轻松实现 API 接口限流:Bucket4j 在 Spring Boot 中的应用
[5]: Jedis使用教程详解
更多推荐


所有评论(0)