限流简单实例

1、限流算法
(1)固定窗口计数器算法
固定窗口其实就是时间窗口。固定窗口计数器算法规定了我们单位时间处理的请求数量。
思路如下:
1)给定一个变量counter来记录当前接口处理的请求数量,初始值为0(代表接口当前1分钟内还未处理请求)。
2)1分钟之内每处理一个请求之后就将counter+1,当counter=33之后(也就是说在这1分钟内接口已经被访问33次的话),后续的请求就会被全部拒绝。
3)等到1分钟结束后,将counter重置0,重新开始计数。
这种限流算法无法保证限流速率,因而无法保证突然激增的流量。
(2)滑动窗口计数器算法
滑动窗口计数器算法相比于固定窗口计数器算法的优化在于:它把时间以一定比例分片。
例如我们的接口限流每分钟处理60个请求,我们可以把1分钟分为60个窗口。每隔1秒移动一次,每个窗口一秒只能处理不大于60(请求数)/60(窗口数)的请求,如果当前窗口的请求计数总和超过了限制的数量的话就不再处理其他请求。
当滑动窗口的格子划分的越多,滑动窗口的滚动就越平滑,限流的统计就会越精确。
(3)漏桶算法
我们可以把发请求的动作比作成注水到桶中,我们处理请求的过程可以比喻为漏桶漏水。我们往桶中以任意速率流入水,以一定速率流出水。当水超过桶流量则丢弃,因为桶容量是不变的,保证了整体的速率。
如果想要实现这个算法的话也很简单,准备一个队列用来保存请求,然后我们定期从队列中拿请求来执行就好了。
(4)令牌桶算法
桶里装的是令牌了,请求在被处理之前需要拿到一个令牌,请求处理完毕之后将这个令牌丢弃(删除)。我们根据限流大小,按照一定的速率往桶里添加令牌。如果桶装满了,就不能继续往里面继续添加令牌了。
2、单机限流
单机限流可以直接使用Google Guava自带的限流工具类RateLimiter,RateLimiter基于令牌桶算法,可以应对突发流量。平滑突发限流就是按照指定的速率放令牌到桶里,而平滑预热限流会有一段预热时间,预热时间之内,速率会逐渐提升到配置的速率。
(1)平滑突发限流
// 桶容量为5且每秒新增5个令牌,即每隔200毫秒新增一个令牌
RateLimiter rateLimiter = RateLimiter.create(5);
for (int i = 0; i < 10; i++) {
    // 消费一个令牌,如果当前桶中有足够令牌则成功(返回值为0),如果桶中没有令牌则暂停一段时间,比如发令牌间隔是200毫秒,则等待200毫秒后再去消费令牌
    double sleepingTime = rateLimiter.acquire(1);
    log.info("get 1 tokens: {}", sleepingTime);
}
运行结果
get 1 tokens: 0.0 
get 1 tokens: 0.199707 
get 1 tokens: 0.192645 
get 1 tokens: 0.199179 
get 1 tokens: 0.19834 
get 1 tokens: 0.198715 
get 1 tokens: 0.199854 
get 1 tokens: 0.188026 
get 1 tokens: 0.19799 
get 1 tokens: 0.198484 
(2)平滑预热限流
// 桶容量为5且每秒新增5个令牌,即每隔200毫秒新增一个令牌。预热时间为3s,即前3s发牌速率会逐渐提升到200毫秒放1个令牌到桶里
RateLimiter rateLimiter = RateLimiter.create(5, 3, TimeUnit.SECONDS);
for (int i = 0; i < 20; i++) {
    double sleepingTime = rateLimiter.acquire(1);
    log.info("get 1 tokens: {}", sleepingTime);
}
运行结果
get 1 tokens: 0.0 
get 1 tokens: 0.572879 
get 1 tokens: 0.51948 
get 1 tokens: 0.465698 
get 1 tokens: 0.411063 
get 1 tokens: 0.358587 
get 1 tokens: 0.304615 
get 1 tokens: 0.250776 
get 1 tokens: 0.205285 
get 1 tokens: 0.19897 
get 1 tokens: 0.198515 
get 1 tokens: 0.198154 
get 1 tokens: 0.198578 
get 1 tokens: 0.198198 
get 1 tokens: 0.198908 
get 1 tokens: 0.198381 
get 1 tokens: 0.198082 
get 1 tokens: 0.198706 
get 1 tokens: 0.198305 
get 1 tokens: 0.198729 

你可能感兴趣的:(其他,java)