91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java如何實現單機接口限流

發布時間:2021-11-25 11:10:35 來源:億速云 閱讀:178 作者:小新 欄目:開發技術

這篇文章主要為大家展示了“java如何實現單機接口限流”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“java如何實現單機接口限流”這篇文章吧。

簡單說就是設定某個接口一定時間只接受固定次數的請求,比如/add接口1秒最多接收100次請求,多的直接拒絕,這個問題很常見,場景也好理解,直接上代碼:

/**
 * 單機限流
 */
@Slf4j
public class FlowLimit {

 //接口限流上限值和限流時間緩存
    private static Cache<String, AtomicLong> localCache = CacheBuilder.newBuilder().maximumSize(100)
            .expireAfterWrite(1000, TimeUnit.MILLISECONDS).build();

 //每個接口的上限緩存
    private static Map<String, Long> maxFlowLimitMap = new ConcurrentHashMap<>();

    private static final FlowLimit instance = new FlowLimit();

 //這塊的目的是初始化每個接口的上限,下面的變量:apiFlowLimitConfigure 
 //實際使用的時候應該是從db或者其他地方獲取設置的每個接口的限流上限值,
 //這樣可以動態的調整接口上限,比如直接修改db,不用發布,就可以調整接口限流值
    static {
        new ScheduledThreadPoolExecutor(1, runnable -> {
            Thread thread = new Thread(runnable, "api-flowLimit-configure");
//            thread.setDaemon(true);
            return thread;
        }).scheduleAtFixedRate(() -> {
            try {
                String apiFlowLimitConfigure = "{\"doAdd\":100}";  //表示/doAdd接口1秒接受100次請求
                Map mapObj = JSONObject.parseObject(apiFlowLimitConfigure, Map.class);
                if(mapObj != null){
                    mapObj.forEach((key, value) -> {
                        if(value != null){
                            instance.setMaxFlowLimit(key.toString(), new Long(value.toString()));
                        }else{
                            log.warn(key + " - 設置接口限流發現限流值為空,設置默認值");
                            instance.setMaxFlowLimit(key.toString(), 100L);
                        }
                    });
                }
            } catch (Exception e) {
                log.error("設置接口限流出現異常{}", e);
            }
        }, 0, 3, TimeUnit.SECONDS);
    }

    public static FlowLimit getInstance() {
        return instance;
    }

    private FlowLimit setMaxFlowLimit(String key, Long maxFlowLimit) {
        maxFlowLimitMap.put(key, maxFlowLimit);
        return this;
    }

    public Boolean isAvailable(String key) {
        return checkAvailable(key, 1L);
    }

    public Boolean isAvailable(String key, Long incrNum) {
        return checkAvailable(key, incrNum);
    }

    private Boolean checkAvailable(String key, Long incrNum){
        Long maxFlowLimit = maxFlowLimitMap.get(key);
        if (null == maxFlowLimit || maxFlowLimit == 0) {
            return true;
        }
        if (incrAndGet(key, incrNum) <= maxFlowLimit.longValue()) {
            return true;
        } else {
            return false;
        }
    }

    private long incrAndGet(String key, final long n) {
        try {
            return localCache.get(key, new Callable<AtomicLong>() {
                @Override
                public AtomicLong call() throws Exception {
                    return new AtomicLong(0);
                }
            }).addAndGet(n);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return 0;
    }

    public long get(String key) {
        return incrAndGet(key, 0);
    }

}

上面這個就是單機限流邏輯,代碼不難,感覺沒必要使用ConcurrentHashMap,不過感覺無所謂了
這段代碼只需要加在需要限流的接口前面:

@GetMapping("doAdd")
public Boolean doAdd(){
    FlowLimit instance = FlowLimit.getInstance(); //單例獲取
    //查看當前的/doAdd接口是否觸發了限流
    Boolean flowLimitFlag = instance.isAvailable("doAdd");
    if(!flowLimitFlag){
        log.warn("觸發限流,拒絕請求");
        return false;
    }
    //doAdd()
    return true;
}

調用實例如上

上面這個限流其實是有一定問題的:比如你限定10秒鐘1000次,在第9.9秒的時候,突然進來1000個請求,然后第10.1秒的時候,攻擊者,又進來1000次請求,這樣,0.2秒之內,進來2000次請求。。。
所以這個時候就需要令牌桶或者其他算法了,其他算法后面再寫

以上是“java如何實現單機接口限流”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西青区| 鹿泉市| 石屏县| 穆棱市| 嘉荫县| 湄潭县| 呼图壁县| 南澳县| 凌源市| 修文县| 台安县| 温泉县| 永仁县| 龙胜| 临汾市| 黎城县| 济源市| 东兰县| 金川县| 新河县| 阳城县| 裕民县| 兴隆县| 奈曼旗| 进贤县| 焦作市| 奉贤区| 建平县| 五原县| 通海县| 安阳市| 吉林省| 西畴县| 即墨市| 湾仔区| 武鸣县| 萝北县| 通城县| 镇安县| 武邑县| 沈丘县|