本文实现了一种基于java的固定时间窗口计数器算法
固定时间窗口计数器算法思想:在固定的时间窗口内,可以允许固定数量的请求进入。超过数量就拒绝或者排队,等下一个时间段进入。
优点:和令牌桶相比,这种算法不需要去等待令牌生成的时间,在新的时间窗口,可以立即处理大量的请求。
缺点:在一个窗口临界点的前后时间,比如时间窗口是1分钟,在59秒和1分01秒同时突发大量请求,极端情况下可能会带来 2 倍的流量,系统可能承受不了这么大的突发性流量。
代码逻辑:新建一个本地缓存,每5s作为一个时间窗口,并作为缓存的key,原子类计数器作为缓存的value。每秒发送随机数量的请求,计算每个时间窗口内的请求数量,超出阈值则限流。
@Slf4j
public class WindowLimiter {
//本地缓存,以时间戳为key,以原子类计数器为value
private LoadingCache<Long, AtomicLong> counter =
CacheBuilder.newBuilder()
.expireAfterWrite(10, TimeUnit.SECONDS)
.build(new CacheLoader<Long, AtomicLong>() {
@Override
public AtomicLong load(Long seconds) throws Exception {
return new AtomicLong(0);
}
});
private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadP