Java中實現(xiàn)接口限流的方案詳解
前言
今天看技術(shù)文章時看到一篇文章在討論接口限流問題,覺得業(yè)務(wù)場景經(jīng)常會使用到,就思考了一下如果是我會怎么實現(xiàn)?常用方案就是計數(shù)器限流方案、時間窗口限流方案和令牌桶限流方案等。這些方案的概念大致也知道,但是實際上也沒有實現(xiàn)過,于是就自己試試實現(xiàn)邏輯,先動手再說。
場景
假設(shè)我們的場景是:
接口10秒內(nèi)最多請求3次
思路
我想到的實現(xiàn)思路是有點時間窗口方案的樣子,大致就是緩存請求時間,然后在每次請求的時候去校驗10秒內(nèi)是否超過3次請求。
圖示
假設(shè)下面是請求的時間(單位:秒),那么前三次都可以請求成功,一個大小為3的數(shù)組緩存數(shù)據(jù)cache就是紅框
所示:
接下去的第四個請求、第五個請求和第一個緩存時間對比,發(fā)現(xiàn)都小于10秒,則請求不通過。
第六個請求時間和第一個請求時間對比,時間大于10秒,所以請求通過,然后更新緩存數(shù)據(jù)cache,緩存的第一個數(shù)據(jù)改為第二個請求時間,緩存第二個數(shù)據(jù)改為第三個請求時間,緩存第三個數(shù)據(jù)改為第6個請求時間,如下圖藍(lán)框
所示,依次類推校驗每次請求是否符合場景要求。
實現(xiàn)
1.聲明一個數(shù)組cache(數(shù)組大小可以為最大請求次數(shù)3),儲存請求時間;
因為我們要對比請求時間,所以講請求緩存下來可以節(jié)省查數(shù)據(jù)庫的時間。因為場景說明限制3次,所以我們只需要知道最后3個請求的時間就可以完成校驗,之前的數(shù)據(jù)可以忽略。
2.首先是初始化情況,當(dāng)請求小于3的時候,請求直接通過,并緩存當(dāng)前請求時間;
3.當(dāng)請求大于等于3的時候,判斷當(dāng)前請求時間和倒數(shù)第三次請求(cache[0]的數(shù)據(jù))的間隔時間是否超過10秒,如果是則通過,否則通過。
通過的時候,要更新緩存數(shù)據(jù),將數(shù)據(jù)前移,這次請求時間就是最后一次請求時間。
// 更新緩存 cache.set(0, cache.get(1)); cache.set(1, cache.get(2)); cache.set(2, now);
4.最后執(zhí)行下代碼驗證下結(jié)果
完整代碼如下所示:
package demo; import cn.hutool.core.date.DateUtil; import lombok.SneakyThrows; import lombok.val; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Random; /** * 限流示例,每分鐘只能請求3次 */ public class LimitFlowDemo { // 記錄最后3次請求時間 List<Long> cache = new ArrayList<>(); int limitTime = 10; public boolean validate() { boolean res = false; val now = DateUtil.currentSeconds(); System.out.println("當(dāng)前時間:" + DateUtil.format(new Date(now * 1000), "HH:mm:ss")); if (cache.size() < 3) { res = true; cache.add(now); } else if(now - cache.get(0) > limitTime){ res = true; // 更新緩存 cache.set(0, cache.get(1)); cache.set(1, cache.get(2)); cache.set(2, now); } System.out.println("請求結(jié)果:" + res); return res; } @SneakyThrows public static void main(String[] args) { Random rd = new Random(); LimitFlowDemo demo = new LimitFlowDemo(); for (int i = 0; i < 1000; i++) { demo.validate(); // Thread.sleep(rd.nextInt(3000)); Thread.sleep(500); } } }
到此這篇關(guān)于Java中實現(xiàn)接口限流的方案詳解的文章就介紹到這了,更多相關(guān)Java接口限流內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringCloud Feign轉(zhuǎn)發(fā)請求頭(防止session失效)的解決方案
這篇文章主要介紹了SpringCloud Feign轉(zhuǎn)發(fā)請求頭(防止session失效)的解決方案,本文給大家分享兩種解決方案供大家參考,感興趣的朋友跟隨小編一起看看吧2020-10-10Mybatis-plus中IService接口的基本使用步驟
Mybatis-plus是一個Mybatis的增強工具,它提供了很多便捷的方法來簡化開發(fā),IService是Mybatis-plus提供的通用service接口,封裝了常用的數(shù)據(jù)庫操作方法,包括增刪改查等,下面這篇文章主要給大家介紹了關(guān)于Mybatis-plus中IService接口的基本使用步驟,需要的朋友可以參考下2023-06-06使用Spring和Redis創(chuàng)建處理敏感數(shù)據(jù)的服務(wù)的示例代碼
許多公司處理的用戶敏感數(shù)據(jù)由于法律限制不能永久存儲,根據(jù)規(guī)定,這些數(shù)據(jù)的存儲時間不能超過預(yù)設(shè)期限,并且最好在用于服務(wù)目的之后就將其刪除,解決這個問題有多種可能的方案,在本文中,我想展示一個利用 Spring 和 Redis 處理敏感數(shù)據(jù)的應(yīng)用程序的簡化示例2025-04-04