一、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使用教程详解

更多推荐