大型网站限流算法的实现和改造

最近写了一个限流的插件,因此避免不了的接触到了一些限流算法。本篇文章就来分析一下这几种常见的限流算法nginx

分析以前

  1. 依我我的的理解来讲限流的话应该灵活到能够针对每个接口来作。好比说一个类里面有5个接口,那么个人限流插件就应该能针对每个接口就行不一样的限流方案。因此呢,既然针对的每一个接口因此就须要一个能够惟一标示这个接口的key(我取的是类名+方法名+入参)。
  2. 分布式限流强烈推荐使用redis+lua或者nginx+lua来实现。
  3. 这里用2个限流条件来作示例讲一下常见的限流算法:
    1. 接口1它10秒钟最大容许访问100次
    2. 接口2它10秒钟最大容许每一个人访问100次。

计数器算法

这个算法能够说是限流算法中最简单的一种算法了。git

核心思想github

计数器算法的意思呢就是当接口在一个时间单位中被访问时,我就记下来访问次数,直到它访问的次数到达上限。redis

涉及变量算法

  1. 接口(key)
  2. 时间单位(expire)
  3. 容许访问多少次(limit)
  4. 访问次数(value)

条件一框架

当一个请求过来时,咱们就会获得这个key。分布式

1
2
3
4
5
6
7
8
9
if(存在key){
   value++;
   if(value>=limit){
   		不能访问
   	}
   }else{
   	添加key,value为1
       设置key过时时间为expire
   }

条件二lua

既然条件一已经实现了,那条件二会复杂么 ?spa

相比于条件一来讲就是同一个key对应了多个用户。那么咱们只须要把key加上用户的信息就能够了。好比说 key_用户一、key_用户2。插件

漏桶算法

核心思想

漏桶算法的意思呢就是一个接口在一个时间单位中容许被访问次数是动态变化的(假如一分钟容许访问60次,那么从开始计时时无论有没有被访问第59秒只容许访问59次,30秒只容许30次)。为何这样呢,由于有另一个线程在进行递减操做

涉及变量

  1. 接口(key)
  2. 时间单位(expire)
  3. 容许访问多少次(limit)
  4. 递减间隔时间(interval)
  5. 递减步长(step)
  6. 剩余可访问次数(value)
  7. key的访问时间(lastUpdateTime)
  8. 当前时间(nowTime)(注意nowTime的取值应为应用取得的时间而不是redis或者nginx取得的时间)

条件一

线程一:

1
2
3
4
5
6
7
8
if(存在key){
   value--;
   if(value<=0){
   		不能访问
   	}
   }else{
   	添加key,设置value为limit
   }

线程二:

1
2
3
while(过去interval时间){
   全部key的value-step
   }

条件二

参考计数器算法条件二实现。

算法升级

能够看到实现漏桶算法的话须要每隔interval时间都要另一条线程去遍历所key的value去作递减操做,那么有没有什么办法能够省略这一步呢。答案是确定有。

1
2
3
4
5
6
7
8
9
10
11
12
13
if(存在key){
   value--;
   if((nowTime-lastUpdateTime)>interval){
   	value=value-(nowTime-lastUpdateTime)/interval*step;
       lastUpdateTime=nowTime;
   }
   if(value<=0){
   		不能访问
   	}
   }else{
   	添加key,设置value为limit;
       lastUpdateTime=nowTime;
   }

令牌桶算法

核心思想

令牌桶算法呢,偏偏是和漏桶算法相反的一个算法,不过仍是推荐你使用这个。这个算法的原理我不讲,我以为聪明的你看了伪代码就明白了。

涉及变量

  1. 接口(key)
  2. 时间单位(expire)
  3. 容许访问多少次(limit)
  4. 递增间隔时间(interval)
  5. 递增步长(step)
  6. 当前可访问次数(value)
  7. key的访问时间(lastUpdateTime)
  8. 当前时间(nowTime)(参照漏桶算法须要注意的点)

条件一

线程一:

1
2
3
4
5
6
7
8
if(存在key){
   value++;
   if(value>=limit){
   		不能访问
   	}
   }else{
   	添加key,设置value为limit
   }

线程二:

1
2
3
while(过去interval时间){
   全部key的value+step
   }

条件二

参考计算器算法条件二实现。

算法升级

参考漏桶算法升级实现。

代码

代码实现请参考个人限流框架https://github.com/2388386839/syj-ratelimit

本文出自http://zhixiang.org.cn,转载请保留。

相关文章
相关标签/搜索