限流

# 限流

关于 Sentinel 限流功能,请点 这里 查看。

# 目录

  • 限流的场景
  • 限流的类型
  • 限流的使用
  • 限流的实现

# 限流的场景

在应用的开发中,我们经常会遇到这样的一些场景,例如:

  • 秒杀
  • 抢红包

等等情况,这些业务都有一个明显的特征:并发量非常高。倘若没做好限流,往往会造成系统崩溃的情况。

# 限流的类型

在 Jboot 中,我们可以对某个url请求进行限流,也可以对某个java方法进行限流。

Jboot 提供了两种方案:

  • TOKEN BUCKET : 令牌桶,它可以配置1秒钟内,允许执行(或请求)多少次。
  • CONCURRENCY : 并发量,可以配置为某个url地址或者某个方法名的并发量支持多少。

# 限流的使用

使用方案1:通过配置来实现

jboot.properties 文件中定义如下:

jboot.limit.enable = true
jboot.limit.rule = /user*:tb:1,/other*:iptb:1,io.jboot.aop*.get*(*):tb:1
jboot.limit.ipWhitelist = 127.0.0.1
  • jboot.limit.enable : 限流功能的开关
  • jboot.limit.rule : 限流规则
  • jboot.limit.ipWhitelist : IP 白名单,多个 IP 用英文逗号隔开,此 IP 下的访问,将不受限流配置的影响

规则说明:

  • 1、可以配置多个规则,每个规则用英文逗号隔开
  • 2、规则分为三个部分,用冒号(:)隔开,分别是:资源、限流类型、限流参数值
  • 3、限流的类型有4种、分别是:tb、cc、iptb 和 ipcc。tb:TOKEN BUCKET(令牌桶,每秒允许访问的数量),cc:CONCURRENCY(并发量),iptb:单个ip每秒允许访问的数量,ipcc:单个ip允许同时的并发量。
  • 4、星号(*)匹配任意字符,也可以是空字符。

在以上配置中,配置了三个规则,分别是:

  • /user*:tb:1
  • /other*:iptb:1
  • io.jboot.aop*.get*(*):cc:1

第一个规则:匹配 /user 开头的所有url地址,每个 url 地址,1 秒钟之内只允许访问 1 次。 第二个规则:匹配 /other 开头的所有url地址,每个 ip 地址在 1 秒钟之内只允许访问 1 次。 第三个规则:匹配 io.jboot.aop 开头的所有包名,并且 get 开头的所有任意参数的方法。并发量为 1。

使用方案2:通过注解 @EnableLimit

例如:

@RequestMapping("/")
public class IndexController extends JbootController {

    @EnableLimit(rate = 1,fallback = "fallbackMethod")
    public void index() {
        renderText("index...." );
    }

    public void fallbackMethod(){
        renderText("fallback...");
    }
}

通过使用 @EnableLimit(rate = 1,fallback = "fallbackMethod") 在方法 index() 方法配置后,当用户访问:http://127.0.0.1:8080时,1秒钟内只有一次访问到 index() 方法,若有多次访问后,自动调用降级放方法 fallbackMethod() 执行。

@EnableLimit 支持的配置如下:

  • resource : 资源名称(不配置的时候默认为方法名,Controller 默认为对应的 url 映射)
  • type:限流的类型,默认为令牌桶。
  • rate:限流的数值,必须配置
  • fallback:降级方法,若配置,此方法必须在当前的类下定义。

# 限流的实现

上文中提到,Jboot 提供了两种限流类型,他们分别是:

  • TOKEN BUCKET : 令牌桶,每秒允许访问的次数。
  • CONCURRENCY : 并发量,和时间无关。

TOKEN BUCKET 令牌桶,是通过 Google Guava 的 RateLimiter 来实现的。

CONCURRENCY 并发量,是通过 Semaphore 实现的,具体代码实现请查看 LimiterInterceptor 。