日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java限频_单个用户及Ip请求频率限制思路(附java实现)

發(fā)布時(shí)間:2025/3/15 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java限频_单个用户及Ip请求频率限制思路(附java实现) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

> 我們熟悉的限流算法漏桶和令牌桶外,很多情況我們還需要考慮當(dāng)個(gè)用戶(ip)訪問頻率控制,避免被惡意調(diào)用。如果是開放平臺限制一天調(diào)用多少次這種粗放的粒度相對好處理一些。如果需要更小時(shí)間粒度控制,譬如一個(gè)10秒時(shí)間窗口最大只允許訪問10次,相對上述粗放粒度我們還需要考慮性能和邊界兩個(gè)問題。在這里提供一種思路給大家,這個(gè)也是我寫的api網(wǎng)關(guān)訪問頻率控制的代碼,經(jīng)過了線上環(huán)境實(shí)踐。

推薦: jeesuite開發(fā)框架,免費(fèi)開源、一站式解決方案。

思路(以10秒限制10次為例)

定義一個(gè)全局map

key為用戶標(biāo)識(ip or sessionId),

value:List<10秒內(nèi)訪問時(shí)間戳>

private Map> accessDatas = new ConcurrentHashMap<>();

啟動一個(gè)定時(shí)器,用于清除10秒前的訪問時(shí)間

cleanScheduledExecutor.scheduleAtFixedRate(new Runnable() {

@Override

public void run() {

long currentTime = System.currentTimeMillis();

List < Long > accessPoints = null;

Iterator < String > idsIterator;

if (gloabalScanFlag == 5) {

//清理空記錄

if (cleanNulling = accessDatas.size() > cleanNullSize) {

log.debug("cleanNulling...");

Set < String > keys = accessDatas.keySet();

for (String key: keys) {

List < Long > points = accessDatas.get(key);

if (points.isEmpty()) {

points = null;

accessDatas.remove(key);

}

}

cleanNulling = false;

}

idsIterator = accessDatas.keySet().iterator();

gloabalScanFlag = 0;

} else {

idsIterator = maybeFullIds.iterator();

gloabalScanFlag++;

}

while (idsIterator.hasNext()) {

accessPoints = accessDatas.get(idsIterator.next());

//

removeExpirePoints(accessPoints, currentTime);

}

}

},

1000, 1000, TimeUnit.MILLISECONDS);

移除過期的請求時(shí)間戳記錄

private int removeExpirePoints(List ponits,long currentTimeMillis){

int removeNums = 0;

if(ponits == null || ponits.isEmpty()){

return removeNums;

}

Iterator pointsIterator = ponits.iterator();

while (pointsIterator.hasNext()) {

if(pointsIterator.next().compareTo(currentTimeMillis - timeWindowMillis) <= 0){

pointsIterator.remove();

removeNums++;

}else{

break;

}

}

return removeNums;

}

頻控檢查

/**

* 訪問頻率檢查

* @param identification 用戶標(biāo)識(ip or sessionId)

* @param uri

* @return

* @copyright http://www.jeesuite.com

*/

private boolean requestFrequencyCheck(String identification, String uri) {

while (cleanNulling);

boolean result = false;

long currentTime = System.currentTimeMillis();

List < Long > accessPoints = accessDatas.get(identification);

try {

if (accessPoints == null) {

accessPoints = new Vector < >(permits);

accessDatas.put(identification, accessPoints);

}

int size;

if ((size = accessPoints.size()) < permits) {

if (size >= putFullQueueSize) {

maybeFullIds.add(identification);

}

result = true;

} else {

int removeNums = removeExpirePoints(accessPoints, currentTime);

result = removeNums > 0;

}

return result;

} finally {

accessPoints.add(currentTime);

}

}

總結(jié)

以上是生活随笔為你收集整理的java限频_单个用户及Ip请求频率限制思路(附java实现)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。