使用场景
限流是高并发的处理方法之一。
高并发处理方案:
缓存:缓存的目的是提升系统访问速度和增大系统处理容量。
降级:降级是当服务出现问题或者影响到核心流程时,需要暂时屏蔽掉,待高峰或者问题解决后再打开。
限流:限流的目的是通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、排队或等待、降级等处理。
令牌桶算法、漏桶算法
限流常见的算法:
令牌桶算法:
- 一个存放固定容量令牌的桶
- 按照固定速率往桶里添加令牌。
- 桶中最多存放指定个数的令牌,当桶满时,新添加的令牌被丢弃或拒绝;
- 令牌桶允许突发的多个请求,只要有令牌就可以处理,支持一次拿3个令牌,4个令牌。
漏桶算法:
- 一个固定容量的漏桶
- 按照常量固定速率流出水滴;
- 如果流入水滴超出了桶的容量,则流入的水滴溢出了,而漏桶容量是不变的。
Maven依赖包:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
RateLimiter限流
- RateLimiter初始化:
RateLimiter limiter = RateLimiter.create(5);
- RateLimiter令牌桶的方法:
create():每秒创建多少令牌;
acquire():获取一个令牌;
acquire(int permits):获取指定个数的令牌;
tryacquire():尝试获取令牌;
tryacquire():尝试获取一个令牌,如果获取不到立即返回;
tryacquire(int permits, long timeout, TimeUnit unit):尝试获取permits个令牌,如果获取不到等待timeout时间;
示例:
public static void runRateLimiter() {
Long start = System.currentTimeMillis();
// 每秒产生10个令牌,也就是说每秒最多执行10个任务
RateLimiter limiter = RateLimiter.create(10);
for(int i = 1; i < 100; i ++ ) {
// 请求RateLimiter, 超过permits(也就是create方法的参数,比如上面的10)会被阻塞,然后等待获取令牌
limiter.acquire();
System.out.println("acquire:" + i );
}
Long end = System.currentTimeMillis();
System.out.println("限流后总耗时:" + (end - start));
}
参考资料:
https://www.iteye.com/blog/jinnianshilongnian-2305117
https://www.jianshu.com/p/5d4fe4b2a726