java限流算法学习笔记

1、计数器限流算法

代码实现:

/**
 * 计数器限流算法
 */
public class CounterLimiter {
    /**
     * 当前时间
     */
    private long timeStamp = System.currentTimeMillis();
    /**
     * 请求数
     */
    private int reqCount = 0;
    /**
     * 每秒限流的最大请求数
     */
    private int limitNum = 100;
    /**
     * 限流时长,3s
     */
    private long interval = 3000L;

    public synchronized Boolean limit ()
    {
				// 也可以使用redis计算,利用redis的自动增加的原子性,redisClient.incr(System.currentTimeMillis() / 1000)
        // 获取当前时间
        long now = System.currentTimeMillis();
        // 处于限流时间内
        if (now < timeStamp + interval){
            // 判断当前请求书是否大于最大请求数
            if (reqCount + 1 > limitNum){
                return true;
            }
            reqCount++;
            return false;
        }
        // 不处于限流时间内,开启新增限流时间
        timeStamp = now;
        reqCount = 0;
        return false;
    }
}

2、滑动时间窗口算法

代码实现:

/**
 * 滑动时间窗口算法
 */
public class SlidingTimeWindowLimiter {
    /**
     * 总的请求数
     */
    private int reqCount = 0;
    /**
     * 每个窗口的请求数
     */
    private LinkedList<Integer> slots = new LinkedList<>();
    /**
     * 每秒限流的最大请求数
     */
    private int limitNum = 100;
    /**
     * 滑动窗口里的每个格子的时间长度,设置1ms
     */
    private long windowLength = 100L;
    /**
     * 滑动窗口里的格式数量,1s内有10个格子
     */
    private int windowNum = 10;

    /**
     * 初始化
     */
    public SlidingTimeWindowLimiter(){
        // 初始化一个滑动窗口
        slots.add(0);
        // 开启线程每隔1ms添加一个滑动窗口
        new Thread(() ->{
            while (true){
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 添加滑动窗口
                slots.add(0);
                // 如果当前滑动窗口已经超过10个
                if(slots.size() > windowNum){
                    // 去掉第一个窗口中的请求数
                    reqCount = reqCount - slots.peekFirst();
                    // 去掉第一个窗口
                    slots.removeFirst();
                }
            }
        }).start();
    }

    /**
     * 限流
     * @return
     */
    public synchronized Boolean limit(){
        // 限流
        if (reqCount + 1 > limitNum){
            return true;
        }
        // 没有限流
        // 设置当前滑动窗口的请求数
        slots.set(slots.size() - 1, slots.peekLast() + 1);
        // 请求数+1
        reqCount++;
        return  false;
    }
}

3、漏桶算法

代码实例:

/**
 * 漏桶算法
 */
public class LeakyBucketLimiter {
    /**
     * 当前时间
     */
    private long timeStamp = System.currentTimeMillis();
    /**
     * 桶的容量(最大能处理的请求数)
     */
    private long capacity = 100;
    /**
     * 桶漏水的速率(每秒能处理的请求数)
     */
    private long rate = 10;
    /**
     * 当前水量(当前累计的请求数)
     */
    private long water = 20;

    public synchronized Boolean limit (){
        long now = System.currentTimeMillis();
        // 先执行漏水,计算剩余水量(计算剩余请求次数)
        water = Math.max(0, water - ((now - timeStamp) / 1000) * rate);
        timeStamp = now;
        // 判断桶容量是否已超
        // 已超桶容量
        if (water + 1 > capacity){
            return true;
        }
        // 没超桶容量
        water++;
        return false;
    }
}

4、令牌桶算法

代码实例:

/**
 * 令牌桶限流算法
 */
public class TokenBucketLimiter {
    /**
     * 当前时间
     */
    private long timeStamp = System.currentTimeMillis();
    /**
     * 桶的容量(最大能处理的请求数)
     */
    private long capacity = 100;
    /**
     * 令牌放入速率(每秒向桶里放入的令牌数量)
     */
    private long rate = 10;
    /**
     * 当前令牌数
     */
    private long tokens = 20;

    public synchronized Boolean limit(){
        // 当前时间
        long now = System.currentTimeMillis();
        // 计算当前桶里剩余的令牌数
        tokens = Math.min(capacity, tokens + (now - timeStamp) * rate);
        timeStamp = now;
        // 桶里没有令牌则限流
        if (tokens < 1){
            return true;
        }
        // 还有令牌则领取令牌
        tokens--;
        return false;
    }

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值