常见限流算法

本文介绍了两种限流算法的Java实现:固定窗口算法和滑动窗口算法。固定窗口算法通过计数器在设定的时间窗口内限制请求次数;滑动窗口算法则利用多个子窗口动态计算平均请求速率,更有效地处理突发流量。代码示例展示了如何在Java中应用这两种算法。
摘要由CSDN通过智能技术生成
package com.baiwang.customize.common.utils;

import java.time.LocalTime;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created in 2022/3/17
 */
public class limiterUtil {

    /**
     * 固定窗口算法
     * 计算器
     */
    static class RateLimiterSimpleWindow {
        //阈值
        private static Integer QPS = 3;
        //时间窗口,毫秒级
        private static long TIME_WINDOWS = 1000;
        //计数器
        private static AtomicInteger REQ_COUNT = new AtomicInteger();

        private static long START_TIME = System.currentTimeMillis();

        //每千毫秒限制请求QPS次
        public synchronized static boolean tryAcquire() {
            if ((System.currentTimeMillis() - START_TIME) > TIME_WINDOWS) {
                REQ_COUNT.set(0);
                START_TIME = System.currentTimeMillis();
            }
            return REQ_COUNT.incrementAndGet() <= QPS;
        }

        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < 10; i++) {
                Thread.sleep(100);
                LocalTime now = LocalTime.now();
                if (!tryAcquire()) {
                    System.out.println(now + "被限流");
                } else {
                    System.out.println(now + "做什么");
                }
            }
        }
    }

    /**
     * 滑动窗口算法
     */
    static class RateLimiterSlidingWindow {
        //阈值
        private int qps = 2;
        //时间窗口总大小毫秒级
        private long windowSize = 1000;
        //多少个子窗口
        private Integer windowCount = 10;
        //窗口列表
        private windowInfo[] windowArray = new windowInfo[windowCount];

        public RateLimiterSlidingWindow(int qps) {
            this.qps = qps;
            long currentTimeMills = System.currentTimeMillis();
            for (int i = 0; i < windowArray.length; i++) {
                windowArray[i] = new windowInfo(currentTimeMills, new AtomicInteger());
            }
        }

        /**
         * 1.计算当前时间创窗口
         * 2.更新当前窗口计数 & 重置过期窗口计数
         * 3.当前QPS是否会超过限制
         */
        public synchronized boolean tryAcquire() {
            long currentTimeMillis = System.currentTimeMillis();
            //1.计算当前时间窗口
            int currentIndex = (int) (currentTimeMillis % windowSize / (windowSize / windowCount));
            //2.更新当前窗口计数 & 重置过期窗口计数
            int sum = 0;
            for (int i = 0; i < windowArray.length; i++) {
                windowInfo windowInfo = windowArray[i];
                if ((currentTimeMillis - windowInfo.getTime()) > windowSize) {
                    windowInfo.getNumber().set(0);
                    windowInfo.setTime(currentTimeMillis);
                }
                if (currentIndex == i && windowInfo.getNumber().get() < qps) {
                    windowInfo.getNumber().incrementAndGet();
                }
                sum = sum + windowInfo.getNumber().get();
            }
            return sum < qps;
        }

        private class windowInfo {
            //窗口开始时间
            private long time;
            //计数器
            private AtomicInteger number;

            public windowInfo(long time, AtomicInteger number) {
                this.number = number;
                this.time = time;
            }

            public long getTime() {
                return time;
            }

            public void setTime(long time) {
                this.time = time;
            }

            public AtomicInteger getNumber() {
                return number;
            }

            public void setNumber(AtomicInteger number) {
                this.number = number;
            }
        }

    }

    public static void main(String[] args) throws InterruptedException {
        int qps = 2, count = 20, sleep = 300, success = count * sleep / 1000 * qps;
        System.out.println(String.format("当前QPS限制为:%d,当前测试次数:%d,间隔:%dms,预计成功次数:%d", qps, count, sleep, success));
        success = 0;
        RateLimiterSlidingWindow rateLimiterSlidingWindow = new RateLimiterSlidingWindow(qps);
        for (int i = 0; i < count; i++) {
            Thread.sleep(sleep);
            if (rateLimiterSlidingWindow.tryAcquire()) {
                success++;
                if (success % qps == 0) {
                    System.out.println(LocalTime.now() + ":success, ");
                } else {
                    System.out.println(LocalTime.now() + ":success, ");
                }
            } else {
                System.out.println(LocalTime.now() + ":fail, ");
            }
        }
        System.out.println();
        System.out.println("实际测试成功次数:" + success);
    }
}

上面是固定窗口算法和滑动窗口算法的实现思路。

参考于:5种限流算法,7种限流方式,挡住突发流量?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值