Java限流之令牌桶算法、漏桶算法

限流在实际使用场景中应用十分广泛,尤其针对并发场景下的高并发,为了保证系统的可用性,我们需要采取一些限流措施降级,以防止非预期的请求对系统压力过大而引起的系统瘫痪。

对于过量的请求一般的措施就是丢掉多余的请求,或者让请求排队,再或者引流

下面说下常用的限流方式:

1.计数器方法

比如在1分钟内限制请求次数不超过100,那我们定义一个变量counter,每来一个请求则counter加1,如果在一分钟之内counter累计超过100,新来的请求则超过限制。然后,超过1s之后,这个counter就重置。这是比较简单的计数器法;

但是这种方法会有一个问题,那就是比如某个人在0:59秒的时候打了100个请求过来,然后,在1min的时候counter就置零了,他又在1:01的时候打了100个请求过来,所以说,在最近的1min之内其实是接收到200个请求,这明显超出了我们的预期,所以说这种方法不满足我们的需求。

聪明的小伙伴一眼就能看出问题所在,其实是我们统计的精度太低了,于是就引出下面的滑动窗口计数法;

2.滑动窗口

比如我们把1min划分成6个小格,则每10s为一个分割单位,比如在0:35分钟来了100个请求,则会落在0:30-0:39这个区间内,当1:01再来100个请求时,显然,最近1分钟内的请求次数超过了100,那么这100个请求则被限制住了,这种是符合我们的预期。但是滑动窗口对存储有比较大的需求,尤其在窗口比较小的情况下不满足需求。

3.漏桶算法

漏桶算法的思路就是,水(请求)先进入漏桶里,漏桶以一定的速度出水(接口响应时间),当水流入速度(接口请求的速度)越来越大时,漏桶就会溢出,然后新来的请求就会被拒绝。无论请求量多大,漏洞的出水速率是不变的,所以针对突发的大流量场景,这种方案是不支持的。

漏洞算法示意图

4.令牌桶算法

令牌桶算法是我们日常使用比较多的方案,它的基本方案是:系统以恒定速率向桶里放入令牌,,如果桶满了则不加。当请求来的时候,从桶里拿走一个令牌,如果桶里没有令牌则阻塞或者拒绝新的请求。令牌桶的另外一个好处是可以方便的改变速度. 一旦需要提高速率,则按需提高放入桶中的令牌的速率. 

可以参考RateLimiter类来进行实际应用。


令牌桶算法示意图

你可能感兴趣的:(Java限流之令牌桶算法、漏桶算法)