常见的限流算法

计数器算法

​ 计数器算法是限流算法里最简单也是最容易实现的一种算法。比如我们规定,对于A接口来说,我们1分钟的访问次数不能超过100个。那么我们可以这么做:在一开始的时候,我们可以设置一个计数器counter,每当一个请求过来的时候,counter就加1,如果counter的值大于100并且该请求与第一个请求的间隔时间还在1分钟之内,那么说明请求数过多;如果该请求与第一个请求的间隔时间大于1分钟,且counter的值还在限流范围内,那么就重置 counter,具体算法的示意图如下:

这个限流算法虽然很简单,但是有一个很大的问题:边界的问题

假设有一个恶意用户,他在0:59时,瞬间发送了100个请求,并且1:00又瞬间发送了100个请求,那么其实这个用户在 1秒里面,瞬间发送了200个请求。我们刚才规定的是1分钟最多100个请求,也就是每秒钟最多1.7个请求,用户通过在时间窗口的重置节点处突发请求, 可以瞬间超过我们的速率限制。用户有可能通过算法的这个漏洞,瞬间压垮我们的应用。

伪代码

public class CounterTest {
    public long timeStamp = getNowTime();
    public int reqCount = 0;
    public final int limit = 100; // 时间窗口内最大请求数
    public final long interval = 1000; // 时间窗口ms

    public boolean grant() {
        long now = getNowTime();
        if (now < timeStamp + interval) {
            // 在时间窗口内
            reqCount++;
            // 判断当前时间窗口内是否超过最大请求控制数
            return reqCount <= limit;
        } else {
            timeStamp = now;
            // 超时后重置
            reqCount = 1;
            return true;
        }
    }

    public long getNowTime() {
        return System.currentTimeMillis();
    }
}

滑动窗口算法

滑动窗口算法弥补了计数器算法的不足。滑动窗口算法把间隔时间划分成更小的粒度。当更小粒度的时间间隔过去后,把过去的间隔请求数减掉,再补充一个空的时间间隔。

如下图所示,把1分钟划分为10个更小的时间间隔,每6s为一个间隔。
在这里插入图片描述

  1. 一个时间窗口为1分钟,滑动窗口分成10个格子,每个格子6秒。
  2. 每过6秒,滑动窗口向右移动1个格子。
  3. 每个格子都有独立的计数器。
  4. 如果时间窗口内所有的计数器之和超过了限流阀值,则触发限流操作。在这里插入图片描述

用户在0:59 时刻发送了100个请求,第10个格子的计数器增加100,下一秒的时候时间窗口向右移动1格,这时再来100个请求就超过了阈值,不会处理这100个请求,这样就避免了计数器场景出现的问题。滑动窗口设置得越精细,限流的效果越好,但滑动窗口的时间间隔(小格子)多了,存储的空间也会增加。

滑动窗口算法基本上是循环10个窗口,如果未超过限流阈值,则会循环每个窗口,再进入下一个窗口的时候,会将第一个窗口给初始化

令牌桶算法

在这里插入图片描述

令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。 当桶满时,新添加的令牌被丢弃或拒绝。

令牌桶算法是一个存放固定容量令牌(token)的桶,按照固定速率往桶里添加令牌。令牌桶算法基本可以用下面的几个概念来描述:

  1. 所有的请求在处理之前都需要拿到一个可用的令牌才会被处理。
  2. 令牌将按照固定的速率被放入令牌桶中。比如每秒放10个。
  3. 桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝。
  4. 请求达到后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理完业务逻辑之后,将令牌直接删除。
  5. 当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上。
  6. 令牌桶有最低限额,当桶中的令牌达到最低限额的时候,请求处理完之后将不会删除令牌,以此保证足够的限流。

漏桶算法

漏桶算法比较形象,设想有一个桶,桶的底部有一个洞,当装上水的时候,水会一滴一滴地从底部漏掉。当装的水太满,水会溢出,但底部漏水的速度还是不变的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值