Bootstrap

resilience4j限流工具的使用

1. 什么是resilience4j

有时我们不想让某个接口被访问得太过频繁,想对访问量进行控制,这时resilience4j就可以发挥作用了。
官方文档:https://resilience4j.readme.io/v1.7.0/docs/getting-started

2. 如何使用resilience4j

resilience4j提供了数种限流的规则,这里我们主要介绍两种:RateLimiter 和 Bulkhead。

2.1 RateLimiter

频率限制器,RateLimiter可以让你控制某个方法在一段时间内的访问量,比如你想限制某个方法在1s内只能被访问10次,就可以使用RateLimiter实现。

我们在springboot种使用RateLimiter,有以下几个步骤:

2.1.1 引入依赖
<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-ratelimiter</artifactId>
    <version>1.7.0</version>
</dependency>
2.1.2 添加配置

在spring配置文件中,添加如下配置

#较为宽松的限流
resilience4j.ratelimiter.instances.rateLimiter_relaxedMod.limit-for-period=60
resilience4j.ratelimiter.instances.rateLimiter_relaxedMod.limit-refresh-period=500ms
resilience4j.ratelimiter.instances.rateLimiter_relaxedMod.timeout-duration=10s

#较为严格的限流
resilience4j.ratelimiter.instances.rateLimiter_strictMod.limit-for-period=10
resilience4j.ratelimiter.instances.rateLimiter_strictMod.limit-refresh-period=1s
resilience4j.ratelimiter.instances.rateLimiter_strictMod.timeout-duration=0
配置属性默认值解释
timeoutDuration5s线程等待获取权限的等待时间
limitRefreshPeriod500ns限制刷新的时间段。在每个周期之后,速率限制器将其权限计数设置回 limitForPeriod 值
limitForPeriod50一个限制刷新期间可用的权限数

上面我们配置了rateLimiter_relaxedMod和rateLimiter_strictMod两种舱壁,这个名字可以自定义,后面在使用RateLimiter的时候可以通过这个名字来指定使用哪种规则。

  • rateLimiter_relaxedMod我们配置了在500ms内允许60个请求通过,如果在500ms周期内60个请求数量已经被消耗完,则第61个请求会阻塞等待10s,当进入下一个500ms周期时,此第61个请求会获得执行权限。

  • rateLimiter_strictMod我们配置了在1s内允许10个请求通过,如果在1s周期内10个请求数量已经被消耗完,则第11个请求会直接报错,不阻塞等待。

2.1.3 方法限流

完成上述配置后,就可以将限流规则引入到方法上了,引入的方式也非常简单,直接在方法上添加注解就可以了。

  @RateLimiter(name = "rateLimiter_relaxedMod")
  public String test1() {
    return "hello world1";
  }

  @RateLimiter(name = "rateLimiter_strictMod")
  public String test2() {
    return "hello world2";
  }

如代码中所示,我们在方法上添加注解RateLimiter,并通过name指定了我们使用哪个RateLimiter作为这个方法的限流规则,这就完成方法的限流了。

注意:注解需要添加到接口的实现上,不能直接添加到接口上,否则不生效。

2.2 Bulkhead

可以翻译为舱壁,Bulkhead的作用是限制一个方法最多同时被多少个线程调用。

我们在springboot种使用Bulkhead,有以下几个步骤:

2.2.1 引入依赖
<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-bulkhead</artifactId>
    <version>1.7.0</version>
</dependency>
2.2.2 添加配置

在spring配置文件中,添加如下配置

#较为宽松的限流
resilience4j.bulkhead.instances.bulkhead_relaxedMod.max-concurrent-calls=50
resilience4j.bulkhead.instances.bulkhead_relaxedMod.max-wait-duration=20ms

#较为严格的限流
resilience4j.bulkhead.instances.bulkhead_strictMod.max-concurrent-calls=25
配置属性默认值解释
maxConcurrentCalls25舱壁允许的最大并行执行量
maxWaitDuration0尝试进入饱和舱壁时应阻塞线程的最长时间

上面我们配置了bulkhead_relaxedMod和bulkhead_strictMod两种舱壁,这个名字可以自定义,后面在使用舱壁的时候可以通过这个名字来指定使用哪种规则。

  • bulkhead_relaxedMod我们配置了最大同时调用线程数是50,如果最大线程数已经达到50,则第51个线程调用此方法时,会阻塞等待20ms,如果20ms内依然没有空位可以进去,则此第51个线程直接返回报错,不再阻塞等待。

  • bulkhead_strictMod我们配置了最大同时调用线程数是25,如果最大线程数已经达到25,则第26个线程调用此方法时,不会阻塞等待,直接返回报错。

2.2.3 方法限流

完成上述配置后,就可以将限流规则引入到方法上了,引入的方式也非常简单,直接在方法上添加注解就可以了。

  @Bulkhead(name = "bulkhead_relaxedMod")
  public String test1() {
    return "hello world1";
  }

  @Bulkhead(name = "bulkhead_strictMod")
  public String test2() {
    return "hello world2";
  }

如代码中所示,我们在方法上添加注解@Bulkhead,并通过name指定了我们使用哪个bulkhead作为这个方法的限流规则,这就完成方法的限流了。

注意:注解需要添加到接口的实现上,不能直接添加到接口上,否则不生效。

2.3 混合使用

我们可以混合使用RateLimiter和Bulkhead,把两个注解同时添加到方法上就行了。

  @Bulkhead(name = "bulkhead_relaxedMod")
  @RateLimiter(name = "rateLimiter_relaxedMod")
  public String test1() {
    return "hello world1";
  }

  @Bulkhead(name = "bulkhead_strictMod")
  @RateLimiter(name = "rateLimiter_strictMod")
  public String test2() {
    return "hello world2";
  }

结合上面两者,方法首先需要获得RateLimiter的令牌才能执行,并且在有足够令牌的前提下,还需要检查Bulkhead是否有足够的并发容量来处理新的请求。

;