好文阅读-Java-限流解决方案

本文介绍了Java中三种流量控制机制:FixedWindowLimiter的固定窗口限流,SlideWindowLimiter的滑动窗口限流,以及BuketLimiter的漏桶算法,它们在并发场景中用于控制请求速率和资源分配。
摘要由CSDN通过智能技术生成

原文链接
原文写的非常好,这里只做一个简单的代码练习,方便回顾

1 固定窗口

public class FixedWindowLimiter {
    /**
     * 限制数量
     */
    private int limitCount;

    /**
     * 窗口大小
     */
    private int windowSize;

    /**
     * 上次时间
     */
    private long last = System.currentTimeMillis();
    /**
     * 计数器
     */
    private static AtomicInteger counter = new AtomicInteger();

    private FixedWindowLimiter(int limitCount, int windowSize)
    {
        this.limitCount = limitCount;
        this.windowSize = windowSize;
    }

    /**
     * 是否拦截
     * @return
     */
    public synchronized boolean tryAcquire() {
        long curTime = System.currentTimeMillis();
        if (curTime - windowSize >= last) {
            // 更新到下一个窗口
            counter = new AtomicInteger();
            last = System.currentTimeMillis() - windowSize;
        }
        if (counter.incrementAndGet() <= limitCount) {
            return true;
        } else {
            return false;
        }
    }
}

2 滑动窗口

public class SlideWindowLimiter {
    /**
     * 窗口大小
     */
    private int windowSize;
    /**
     * 窗口内部划分
     */
    private int splitCount;
    /**
     * 限制数量
     */
    private int limitCount;
    /**
     * 窗口右端点
     */
    private long windowRight;
    /**
     * 计数器
     */
    private int[] counters;
    /**
     * 计数器的下标
     */
    private int idx;
    /**
     * 将这个大窗口继续分为小窗口
     */
    private int gap;

    /**
     * 整个窗口请求数量
     */
    private long totalCount = 0;
    public SlideWindowLimiter(int windowSize, int splitCount, int limitCount) {
        this.windowSize = windowSize;
        this.splitCount = splitCount;
        this.limitCount = limitCount;
        gap = windowSize / splitCount;
        windowRight = System.currentTimeMillis() + gap;
        counters = new int[splitCount];
    }
    public synchronized boolean tryAcquire() {
        long curTime = System.currentTimeMillis();
        if (windowRight - curTime <= 0) {
            do {
                // 之所以要先加是因为 我们淘汰的是第一个窗口 
                // 利用取模的操作 +1 后如果是要往右滑动我们将最左边的小窗口移除
                idx = (++ idx) % splitCount;
                totalCount -= counters[idx];
                counters[idx] = 0;
                windowRight += gap;
            } while (windowRight < curTime);
        }
        if (totalCount <= limitCount) {
            counters[idx] ++;
            totalCount ++;
            return true;
        } else {
            return false;
        }
    }
}

3 漏桶算法

public class BuketLimiter {
    /**
     * 桶的容量
     */
    private int capacity;
    /**
     * 桶的出水速度
     */
    private int spaceTime;
    /**
     * 速率
     */
    private int speed;

    private long leakTime;
    private AtomicLong counter = new AtomicLong();
    public BuketLimiter(int spaceTime, int capacity, int speed) {
        this.spaceTime = spaceTime;
        this.capacity = capacity;
        this.speed = speed;
    }
    public synchronized boolean tryAcquire() {
        // 如果桶 为空
        if (counter.get() == 0) {
            leakTime = System.currentTimeMillis();
            counter.incrementAndGet();
            return counter.get() < capacity;
        }
        // 进行漏水
        // 计算当前时间要漏出的数量
        long leakCnt = speed * (System.currentTimeMillis() - leakTime) / spaceTime;
        if (leakCnt != 0) {
            long oCnt = counter.get();
            oCnt -= leakCnt;
            counter.set(Math.max(0, oCnt));
            leakTime = System.currentTimeMillis();
        }
        if (counter.get() < capacity) {
            counter.incrementAndGet();
            return true;
        } else {
            return false;
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值