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

com.ghp.request.limiter.impl.LeakyBucketLimiter 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 LeakyBucketLimiter implements Limiter {

    /**
     * 记录上一次请求时漏桶的容量
     * 如果初始容量为 10,表示一个桶最多同时处理10个请求,超出部分就会被限流
     * key是接口名,value是漏桶的剩余容量
     */
    private Map capacityMap = 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();
        int capacity = requestLimitAnnotation.capacity();

        long now = System.currentTimeMillis();
        // 上一次请求时桶的容量(初始状态为桶为空)
        int preCapacity = capacityMap.getOrDefault(methodName, 0);
        // 上一次请求时的时间戳(初始状态为当前时间)
        long prevTimestamp = this.timestampMap.getOrDefault(methodName, now);
        // 上一次请求与当前请求的时间间隔
        int interval = (now - prevTimestamp) == 0 ? 0 : (int) ((now - prevTimestamp) / 1000);

        // 当前桶的容量 = 上一次请求时桶的容量 - 时间间隔中漏出的水
        int curCapacity = preCapacity - interval * qps;
        curCapacity = Math.max(curCapacity, 0);
        // 判断当前桶的容量是否足够
        if ((curCapacity + 1) > capacity) {
            // 当前容量不够,需要限流
            return true;
        }
        // 当前容量足够,则更新容量和时间戳
        timestampMap.put(methodName, now);
        capacityMap.put(methodName, curCapacity + 1);
        return false;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy