上文简单介绍过限流中的计数器法,详情参考:限流算法之计数器算法(Java实现)

计数器法有个缺点就是临界问题。举个例子,我们限制每分钟调用接口不能超过1000次,用计数器法实现时,如果恶意用户在01:59秒一秒内发送1000次调用,又在02:01秒调用1000次,2秒内调用了2000次,这样就不能很好地限流了,也失去保护资源的作用。


解决上面问题可以用滑动窗口,令牌桶或者漏桶算法,今天先用滑动窗口算法实现。

如果对滑动窗口不熟悉可以先了解下TCP的滑动窗口协议。限流中的滑动窗口可以简单理解为,设定的单位时间就是一个窗口,窗口可以分割多个更小的时间单元,随着时间的推移,窗口会向右移动。比如一个接口一分钟限制调用1000次,1分钟就可以理解为一个窗口,可以把1分钟分割为10个单元格,每个单元格就是6秒。


光说不练等不白干,下面就用一个简单的链表来简单实现,

定义一个Node,Node中需要记录起始时间和调用计数器,并且有个指向下一个Node的变量,把所有的Node组成一个环用lastNode记录上次窗口的移动位置,再次访问时,先确定窗口滑动的位置,让窗口滑动到指定位置获取当前窗口的计数器的总数,如果不大于限制,当前的Node的计数器加一下面就是具体的实现代码,如果需要源码请私信。

简单解释其中的几个变量的作用

slot单位时间分割的数据limit单位时间限制的数量timeUnit自定义的枚举类,为单位时间slotTime最小单元格的时间长度,单位是毫秒



用滑动窗口来限流时,设置的单位时间越小,分割的时间越多,统计就会越准确。

后续介绍令牌桶或者漏桶算法