常見(jiàn)的限流方法有計(jì)數(shù)器、漏斗算法、令牌桶算法,各自也有各自的優(yōu)缺點(diǎn)
一 計(jì)數(shù)器限流方法
計(jì)數(shù)器算法比較簡(jiǎn)單,即一段時(shí)間內(nèi)的調(diào)用次數(shù)是有上限的,當(dāng)大于最大請(qǐng)求次數(shù),則拒絕服務(wù)
計(jì)數(shù)器算法偽代碼:
public class CounterDemo {
public long timeStamp = getNowTime();
public int reqCount = 0;
public final int limit = 100; // 時(shí)間窗口內(nèi)最大請(qǐng)求數(shù)
public final long interval = 1000; // 時(shí)間窗口ms
public boolean grant() {
long now = getNowTime();
if (now < timeStamp + interval) {
// 在時(shí)間窗口內(nèi)
reqCount++;
// 判斷當(dāng)前時(shí)間窗口內(nèi)是否超過(guò)最大請(qǐng)求控制數(shù)
return reqCount <= limit;
} else {
timeStamp = now;
// 超時(shí)后重置
reqCount = 1;
return true;
}
}
}
優(yōu)點(diǎn):原理簡(jiǎn)單,利于實(shí)現(xiàn)
缺點(diǎn):
- 不能很好地防止瞬時(shí)流量,在01-02秒之間,請(qǐng)求假如都在1.1秒處進(jìn)來(lái),導(dǎo)致瞬時(shí)流量很大,所以使用計(jì)數(shù)器方法時(shí),要預(yù)估好服務(wù)的瞬時(shí)承載能力
-
不能避免抖動(dòng)問(wèn)題
image.jpeg
如上圖,假設(shè)1秒內(nèi)最大請(qǐng)求數(shù)為100,所以在1-2秒之間最多只能有100次,在02秒時(shí)請(qǐng)求次數(shù)會(huì)被重置為0,重新計(jì)算,這樣極端情況會(huì)在存在在1.5-2.5秒之間的請(qǐng)求總數(shù)是200
二 漏斗限流方法
漏斗算法思想是將所有請(qǐng)求先存到一個(gè)桶里。若此刻桶容量沒(méi)滿,表示當(dāng)前請(qǐng)求是可以訪問(wèn)資源。若滿了,則拒絕服務(wù)。同時(shí)桶會(huì)以固定速率取出桶里的請(qǐng)求來(lái)處理
具體實(shí)現(xiàn)方法可以將請(qǐng)求先暫存到一個(gè)隊(duì)列中,若隊(duì)列已滿,則拒絕該請(qǐng)求。同時(shí)有一個(gè)周期性定時(shí)任務(wù)來(lái)消費(fèi)隊(duì)列里的數(shù)據(jù)
從實(shí)現(xiàn)可以看出,不管請(qǐng)求有多少或者瞬時(shí)流量有多大,請(qǐng)求的處理是固定速率的,所以令牌桶油流量整形的功能,具體實(shí)現(xiàn)代碼可以參考:限流-令牌桶實(shí)現(xiàn)(go版本)
相對(duì)計(jì)數(shù)器方法,令牌桶能有效避免抖動(dòng)的問(wèn)題,但當(dāng)瞬時(shí)請(qǐng)求量很大時(shí),后續(xù)的請(qǐng)求很有可能由于得不到及時(shí)處理而超時(shí)
三 令牌桶方法
當(dāng)一個(gè)請(qǐng)求進(jìn)來(lái)時(shí),它要先獲取一個(gè)token,若獲取成功,則可以訪問(wèn),若不成功,則會(huì)拒絕服務(wù)。存放令牌的地方就是令牌桶,令牌桶中的令牌會(huì)以固定速率生成
具體的令牌桶偽代碼:
public class TokenBucketDemo {
public long timeStamp = getNowTime();
public int capacity; // 桶的容量
public int rate; // 令牌放入速度
public int tokens; // 當(dāng)前令牌數(shù)量
public boolean grant() {
long now = getNowTime();
// 先添加令牌
tokens = min(capacity, tokens + (now - timeStamp) * rate);
timeStamp = now;
if (tokens < 1) {
// 若不到1個(gè)令牌,則拒絕
return false;
}else {
// 還有令牌,領(lǐng)取令牌
tokens -= 1;
return true;
}
}
}
令牌桶能夠承載一定的瞬時(shí)流量,并且也有一些廣泛的應(yīng)用,如Guava中基于令牌桶算法實(shí)現(xiàn)的限流器,阿里出品的sentinel
參考:
