All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ghp.request.limiter.impl.FixedWindowCountLimiter Maven / Gradle / Ivy

package com.ghp.request.limiter.impl;

import com.ghp.request.annotation.RequestLimit;
import com.ghp.request.limiter.Limiter;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ghp
 * @title 固定窗口计数限流器
 * @description
 */
public class FixedWindowCountLimiter implements Limiter {
    /**
     * 记录上一次请求时漏桶的容量
     * 如果初始容量为 10,表示一个桶最多同时处理10个请求,超出部分就会被限流
     * key是接口名,value是接口的当前窗口内的请求数量
     */
    private Map countMap = new ConcurrentHashMap<>();
    /**
     * 记录接口的上一次请求起始时间
     * key是接口名,value是上一次请求的时间戳
     */
    private Map timestampMap = new ConcurrentHashMap<>();


    /**
     * 限流
     *
     * @param methodName
     * @param requestLimitAnnotation
     * @return true-发生限流 false-未限流
     */
    @Override
    public boolean limit(String methodName, RequestLimit requestLimitAnnotation) {
        int qps = requestLimitAnnotation.qps();
        long interval = requestLimitAnnotation.interval();

        long now = System.currentTimeMillis();
        // 窗口中当前的请求数量
        int count = countMap.getOrDefault(methodName, 0);
        // 上一次请求的时间戳(不存在时,则以当前时间为起始)
        long preTimestamp = timestampMap.computeIfAbsent(methodName, key -> now);

        // 判断当前请求是否在当前时间窗口
        if (now > preTimestamp + interval) {
            // 当前请求不在当前时间窗口,直接开启新窗口,并且重置请求次数
            countMap.put(methodName, 0);
            timestampMap.put(methodName, now);
            return false;
        }
        // 当前请求在当前时间窗口,判断是否超过请求阈值
        if (qps < (count + 1)) {
            // 超过阈值,限流
            return true;
        }
        // 未超过阈值,更新窗口中的请求数
        countMap.put(methodName, count + 1);
        return false;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy