流控或者叫限流芹助,可以通過(guò)控制流量來(lái)保護(hù)我們的系統(tǒng)不被大流量或者異常流量沖垮,常用的限流算法有:計(jì)數(shù)器算法、令牌桶算法状土、漏桶算法无蜂。
計(jì)數(shù)器算法
計(jì)數(shù)器算法最簡(jiǎn)單,可以實(shí)現(xiàn)在指定的時(shí)間段內(nèi)流量不能超過(guò)多少蒙谓,比如同一個(gè)ip在1秒內(nèi)請(qǐng)求次數(shù)不能超過(guò)100次這種情形斥季。
需要使用兩個(gè)map,一個(gè)用來(lái)記錄同一個(gè)ip訪問(wèn)的次數(shù)累驮,一個(gè)用來(lái)記錄同一個(gè)ip上次訪問(wèn)的時(shí)間戳泻肯。防止map無(wú)限制增長(zhǎng),可以單獨(dú)開啟一個(gè)線程慰照,用來(lái)定時(shí)清除超過(guò)時(shí)間窗口的ip數(shù)據(jù)灶挟。
計(jì)數(shù)器算法可能會(huì)產(chǎn)生突刺,請(qǐng)求集中到達(dá)處理后毒租,后面時(shí)間就會(huì)空閑掉稚铣。
示例代碼如下:
public class IPCounter {
/**
* 保存ip訪問(wèn)的次數(shù)
* key:ip
* value:訪問(wèn)次數(shù)
*/
private Map<String, AtomicInteger> counterMap = new ConcurrentHashMap<>();
/**
* 保存ip訪問(wèn)的時(shí)間
* key:ip
* value:時(shí)間戳
*/
private Map<String, Long> timeMap = new ConcurrentHashMap<>();
/**
* 指定的次數(shù)
*/
private int countRule;
/**
* 指定的時(shí)間,毫秒
*/
private long timeRule;
public IPCounter(int countRule, long timeRule) {
this.countRule = countRule;
this.timeRule = timeRule * 1000;
}
public boolean allow(String ip) {
Long time = timeMap.get(ip);
Long now = System.currentTimeMillis();
// 不存在或者上一個(gè)時(shí)間窗口已經(jīng)過(guò)去墅垮,重置時(shí)間和計(jì)數(shù)器
if (time == null || (now - time) > timeRule) {
timeMap.put(ip, now);
counterMap.put(ip, new AtomicInteger());
}
AtomicInteger count = counterMap.get(ip);
int temp = 1;
if (count != null) {
temp = count.incrementAndGet();
}
return temp <= countRule;
}
public static void main(String[] args) {
// 10秒不能超過(guò)5次
IPCounter counter = new IPCounter(5, 10);
String ip = "192.168.1.1";
System.out.println(counter.allow(ip));
System.out.println(counter.allow(ip));
System.out.println(counter.allow(ip));
System.out.println(counter.allow(ip));
System.out.println(counter.allow(ip));
System.out.println(counter.allow(ip));
}
}
漏桶算法
漏桶算法惕医,漏桶的容量是固定的,大批流量進(jìn)來(lái)算色,超過(guò)漏桶數(shù)量的拋棄掉抬伺,進(jìn)入到漏桶的請(qǐng)求可以勻速流出。
漏桶算法能夠限制請(qǐng)求的速率灾梦。
令牌桶算法
令牌桶算法是以固定的速度往桶里產(chǎn)生令牌峡钓,桶滿了新的令牌被丟棄或者拒絕,請(qǐng)求到達(dá)的時(shí)候會(huì)先從桶里獲取令牌若河,再繼續(xù)執(zhí)行能岩。
令牌桶算法可以限制請(qǐng)求調(diào)用速率,也允許一定程度的突發(fā)調(diào)用萧福。
可以使用guava包中的令牌桶算法限流器拉鹃。
源碼:https://github.com/dachengxi/APIGateway
原文鏈接:https://cxis.me/2020/04/09/APIGateway%E4%B8%AD%E6%B5%81%E6%8E%A7%E4%BB%8B%E7%BB%8D/