四大限流算法

限流用在接口调用:

1、计数器限流算法:

大概思路:限制1S内的请求数量最大为100,否则限流。

timeStamp:请求开始时间

interval:时间间隔,1S

算法中 now< timeStamp + interval的意思是当前时间是不是在1S的时间间隔内。else的意思是当前时间已经不在上一次的1S内了,则将起始时间定为为now,请求次数置为1。

计数器算法的缺点:

有可能相邻的两个1S内,第一个1S后半段的(0.5秒)突发了60个访问量,第二个1S的前半段突发60个访问量,那就不符合了1S内的100的限流。

2、滑动窗口限流算法:

由于计数器算法的精度太低,为了解决计数器算法突发1S内访问超出限制数量的问题,所以推出了滑动时间窗口算法。

思路:将1S内的时间分成10个100毫秒,最近的1S内,往前数10个格子的数量。

public class SlidingTimeWindowLimiter {
    //服务在最近1秒内的访问次数,可以放在Redis中,实现分布式系统的访问计数
    private int reqCount;
    //使用LinkedList来记录滑动窗口的10个格子
    private LinkedList<Integer> slots = new LinkedList<>();
    //每秒限流的最大请求数
    private int limitNum = 100;
    //滑动时间窗口里的每个格子的时间长度,单位ms
    private long windowlength = 100L;
    //滑动时间窗口里的格子数量
    private int windowNum = 10;

    /**
     * 构造函数
     */
    public SlidingTimeWindowLimiter() {
        slots.addLast(0);
        new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(windowlength);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //100ms后加一个窗口
                slots.addLast(0);
                //格子数量超出10个,超出1S了。
                if (slots.size() > windowNum) {
                    //第11的格子处,请求的总数 = 请求总数 - 第一个格子的请求次数
                    reqCount = reqCount - slots.peekFirst();
                    slots.removeFirst();
                    System.out.println("");
                }
            }
        }).start();
    }

    public synchronized Boolean limit() {
        if (reqCount + 1 > limitNum) {
            return true;
        }
        slots.set(slots.size() - 1, slots.peekLast() + 1);
        reqCount++;
        return false;
    }

    public static void main(String[] args) {
        SlidingTimeWindowLimiter windowLimiter = new SlidingTimeWindowLimiter();
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 160; i++) {
            final int n = i;
            if (n == 105) {
                try {
                    Thread.sleep(1000);
                    System.out.println("等了1S");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            executorService.submit(() -> {
                System.out.println("当前i是多少:" + n + " 限流吗:" + windowLimiter.limit() + " 当前请求次数:" + windowLimiter.reqCount);
            });
        }
    }
}

3、漏桶算法:

思路:由于处理请求的速度一样。用可接受的请求数量来判断是否要限流。

如果水未满,则可以继续加水(继续接受请求),否则拒绝加水(拒绝请求)。

4、令牌桶算法:

以恒定的速率产生令牌,桶满则丢弃多余的令牌。请求进来的时候获取到令牌则放行,否则拒绝请求。

产生令牌的速度一样,但是消耗令牌的速度可以不一样。

令牌的数量为0则被限流,否则通行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值