限流技术总结

     

限流技术主要有以下几种

  1. 信号量
  2. 计数器
  3. 滑动窗口
  4. 漏桶算法
  5. 令牌桶算法
  6. 分布式限流

信号量:信号量实际上就是限制系统的并发量,来达到限流的目的。常见的用法是:创建Semaphore,指定permit的数量。在方法开始时,调用Semaphore.acquire()或者Semaphore.tryAcquire()来获取permit,并在方法返回前,调用Semaphore.release()来返还permit。(线程方面)

计数器:

计数器的方案比较简单。比如限制1秒钟内请求数最多为10个,每当进来一个请求,则计数器+1。当计数器达到上限时,则触发限流。时间每经过1秒,则重置计数器。

滑动窗口:

滑动窗口本质上也是一种计数器,只不过它的粒度更细。比如限制qps为1000,设定窗口大小为10,则每个窗口的时间间隔为100ms。每次窗口滑动时,重置的是前1s至900ms之间内的计数,而不是完整的1s。

示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

public class RateLimiter {
   
private LinkedList deque = new LinkedList<>();
   
private int windowSize;
   
private int windowIntervalMilliSeconds;
   
private int currentWindowPermits;

   
private long updateTimeStamp;
   
private int intervalMilliSeconds;
   
private int maxPermits;
   
private long storedPermits;

   
public RateLimiter(int maxPermits, int windowSize) {
       
this(maxPermits, 1, windowSize);
    }

   
public RateLimiter(int maxPermits, int intervalSeconds, int windowSize) {
       
this.maxPermits = maxPermits;
       
this.intervalMilliSeconds = intervalSeconds * 1000;
       
this.windowSize = windowSize;
       
this.windowIntervalMilliSeconds = intervalMilliSeconds / windowSize;
    }

   
public synchronized Boolean acquire(int permits) {
       
while (true) {
           
long now = System.currentTimeMillis();
           
if (now < updateTimeStamp + windowIntervalMilliSeconds) {
                
if (storedPermits + permits + currentWindowPermits <= maxPermits) {
                    currentWindowPermits += permits;
                    updateTimeStamp = now;
                   
return true;
                }
else {
                   
return false;
                }
            }
else {
                updateTimeStamp = now;
                deque.offerLast(currentWindowPermits);
                storedPermits += currentWindowPermits;
                currentWindowPermits =
0;
               
while (deque.size() > windowSize) {
                    storedPermits -= deque.removeFirst();
                }
            }
        }
    }
}

滑动窗口仍然没有解决计数器的问题。

漏桶算法:

漏桶(Leaky Bucket)算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率。

令牌桶算法的原理是,系统以固定的速率往令牌桶中放入令牌;当请求进来时,则从桶中取走令牌;当桶中令牌为空时,触发限流。

令牌桶与漏桶相比,好处在于它支持突发流量。

Guava中的RateLimiter提供了令牌桶算法的实现,我们可以直接使用。有关原理的说明请参考:Guava RateLimiter分析

 

 

 

 

 

 

你可能感兴趣的:(网站优化)