【限流算法】java实现固定时间窗口算法

本文实现了一种基于java的固定时间窗口计数器算法

固定时间窗口计数器算法思想:在固定的时间窗口内,可以允许固定数量的请求进入。超过数量就拒绝或者排队,等下一个时间段进入。

优点:和令牌桶相比,这种算法不需要去等待令牌生成的时间,在新的时间窗口,可以立即处理大量的请求。
缺点:在一个窗口临界点的前后时间,比如时间窗口是1分钟,在59秒和1分01秒同时突发大量请求,极端情况下可能会带来 2 倍的流量,系统可能承受不了这么大的突发性流量。

代码逻辑:新建一个本地缓存,每5s作为一个时间窗口,并作为缓存的key,原子类计数器作为缓存的value。每秒发送随机数量的请求,计算每个时间窗口内的请求数量,超出阈值则限流。

@Slf4j
public class WindowLimiter {

    //本地缓存,以时间戳为key,以原子类计数器为value
    private LoadingCache counter =
            CacheBuilder.newBuilder()
                    .expireAfterWrite(10, TimeUnit.SECONDS)
                    .build(new CacheLoader() {
                        @Override
                        public AtomicLong load(Long seconds) throws Exception {
                            return new AtomicLong(0);
                        }
                    });
    private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
    //设置限流阈值为15
    private long limit = 15;

    /**
     * 固定时间窗口
     * 每隔5s,计算时间窗口内的请求数量,判断是否超出限流阈值
     */
    private void fixWindow() {
        scheduledExecutorService.scheduleWithFixedDelay(() -> {
            try {
                // time windows 5 s
                long time = System.currentTimeMillis() / 5000;
                //每秒发送随机数量的请求
                int reqs = (int) (Math.random() * 5) + 1;
                long num = counter.get(time).addAndGet(reqs);
                log.info("time=" + time + ",num=" + num);
                if (num > limit) {
                    log.info("限流了,num=" + num);
                }
            } catch (Exception e) {
                log.error("fixWindow error", e);
            } finally {
            }
        }, 0, 1000, TimeUnit.MILLISECONDS);
    }
}

输出结果:

20:04:55.508 [pool-1-thread-3] INFO com.example.demo.limit.WindowLimiter - time=314815739,num=4
20:04:56.510 [pool-1-thread-3] INFO com.example.demo.limit.WindowLimiter - time=314815739,num=7
20:04:57.516 [pool-1-thread-3] INFO com.example.demo.limit.WindowLimiter - time=314815739,num=10
20:04:58.521 [pool-1-thread-3] INFO com.example.demo.limit.WindowLimiter - time=314815739,num=11
20:04:59.526 [pool-1-thread-3] INFO com.example.demo.limit.WindowLimiter - time=314815739,num=14
20:05:00.553 [pool-1-thread-3] INFO com.example.demo.limit.WindowLimiter - time=314815740,num=3
20:05:01.553 [pool-1-thread-3] INFO com.example.demo.limit.WindowLimiter - time=314815740,num=5
20:05:02.558 [pool-1-thread-3] INFO com.example.demo.limit.WindowLimiter - time=314815740,num=9
20:05:03.564 [pool-1-thread-3] INFO com.example.demo.limit.WindowLimiter - time=314815740,num=14
20:05:04.569 [pool-1-thread-3] INFO com.example.demo.limit.WindowLimiter - time=314815740,num=17
20:05:04.570 [pool-1-thread-3] INFO com.example.demo.limit.WindowLimiter - 限流了,num=17
 

你可能感兴趣的:(java,算法)