您好,登錄后才能下訂單哦!
這篇文章主要介紹如何實現API接口限流,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
同樣,在互聯網行業中,也存在這樣得場景,我們把它稱為——限流,為什么要限流呢,原因如下:
在系統上線初期,用戶量和訪問量不大得時候,一般部署幾臺應用服務器,數據庫做一個讀寫分離就基本上抗得住,但隨著時間的推移,業務的發展,用戶量和日活得增加,系統所承受的壓力越來越大,我么都知道,應用服務器擴容很方便,但數據庫擴容就有些麻煩,如果請求數據庫的量太大的話,或者遇到惡意攻擊,數據庫極有可能宕機,最后導致整個網站不可用。
為了避免這樣的事情發生,我們通常要限制住用戶的請求次數。對于合法的用戶,我們要限制單位時間內用戶調用接口的次數,對于惡意攻擊者,直接將他放入黑名單中。
我們通常用Redis中的zset數據結構來做限流。由于zset底層是用跳躍表存儲數據的,按score字段從小到大排序,我們可以把時間戳存入score字段。隨著時間的流逝,把每一次請求的時間戳存入score中,而member呢?隨便存儲什么無所謂啦,但不要存儲太大的數據。如下圖:
假如我們要求接口的調用一分鐘不能超過100次,那么圖中橙色矩形區域是一個時間段范圍內的時間窗口,矩形的有邊框是當前時間,它隨著時間的流逝一點一點向右移動,矩形左邊框是1min前,矩形的寬度就是1min。我們通過Redis的zcount命令很容易計算出這個時間范圍內的數據量,如果數據量超出100,說明用戶請求的太快了,應該進行限流的操作。下面來看一段簡單的代碼:
/**
* 基于zset限流
* @param key redis key
* @param maxCount 指定時間內最大通過個數
* @param timeRange 時間窗范圍,單位:秒
* @return 是否可以繼續請求
*/
public static boolean rateLimiterByZset(String key,int maxCount,int timeRange){
try (Jedis jedis = jedisPool.getResource()) {
long currentTime = new Date().getTime(); //當前時間戳
long secondTime = currentTime-timeRange*1000; //second秒前的時間戳
long memberCount = jedis.zcount(key,secondTime,currentTime);
if(memberCount >= maxCount){
return false;
}
jedis.zadd(key,currentTime,currentTime+"");
//刪除時間框外的數據,因為它們已經沒有用了
jedis.zremrangeByScore(key,0,secondTime);
}
return true;
}
哈哈,就這么簡單。有一點要注意的是,請大家及時刪除時間框(也就是上圖中左邊框外)范圍外的數據,因為它們已經沒有用了,留著非常消耗內存資源。
大家會不會有這樣的疑問:對zset操作這么頻繁,會不會有性能上的問題呀?其實大家不必太擔心,畢竟Redis的數據結構都是經過精心設計的,性性能很高,大家可以參考小編的這篇文章,來學習Redis的數據結構。
從數據存儲角度分析Redis性能為何如此高
劉蒞,公眾號:向代碼致敬從數據存儲角度分析Redis性能為何如此高
測試程序和輸出效果如下:
@Test public void test1() throws Exception{ int i = 1; while(true){ Thread.sleep(5); boolean flag = RedisRateLimiter.rateLimiterByZset("keysss",10,1); if(flag){ System.out.println("第"+i+"個請求成功"); }else{ System.out.println("第"+i+"個被限流"); } i++; } }
第1個請求成功第2個請求成功第3個請求成功第4個請求成功第5個請求成功第6個請求成功第7個請求成功第8個請求成功第9個請求成功第10個請求成功第11個被限流第12個被限流...第42個被限流第43個被限流第44個請求成功第45個請求成功第46個請求成功第47個請求成功第48個請求成功第49個請求成功第50個請求成功第51個請求成功第52個請求成功第53個請求成功第54個被限流第55個被限流...
以上是“如何實現API接口限流”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。