1、場景
我們知道,硬件設備或是服務器之類的通信速率或是服務器的響應速率是有限制的,當瞬時大量通信量情況下需要對速率進行限制,否則可能會出現宕機等服務無法提供的故障。
兩個比較常用的算法有令牌桶算法、漏桶算法,是目前最常用的流量限制的方法。
2、漏桶算法
如上圖所示,我們假設系統是一個漏桶,當請求到達時,就是往漏桶里“加水”,而當請求被處理掉,就是水從漏桶的底部漏出。水漏出的速度是固定的,當“加水”太快,桶就會溢出,也就是“拒絕請求”。從而使得桶里的水的體積不可能超出桶的容量。
上面的分析可以看出,該算法存在三個變量:桶的容量capacity,水漏出的速度rate,以及當前的水量water。
算法偽代碼如下:
long timeStamp=getNowTime();
int capacity; // 桶的容量
int rate ; //水漏出的速度
int water; //當前水量
bool grant() {
//先執行漏水,因為rate是固定的,所以可以認為“時間間隔*rate”即為漏出的水量
long now = getNowTime();
water = max(0, water- (now - timeStamp)*rate);
timeStamp = now;
if (water < capacity) { // 水還未滿,加水
water ++;
return true;
} else {
return false;//水滿,拒絕加水
}
}
3、令牌桶算法
令牌桶算法的原理是系統會以一個恒定的速度往桶里放入令牌,而如果請求需要被處理,則需要先從桶里獲取一個令牌,當桶里沒有令牌可取時,則拒絕服務。從原理上看,令牌桶算法和漏桶算法是相反的,一個“進水”,一個是“漏水”。
long timeStamp=getNowTime();
int capacity; // 桶的容量
int rate ; //令牌放入速度
int tokens; //當前水量
bool grant() {
//先執行添加令牌的操作
long now = getNowTime();
tokens = max(capacity, tokens+ (now - timeStamp)*rate);
timeStamp = now;
//令牌已用完,拒絕訪問
if(tokens<1){
return false;
}else{//還有令牌,領取令牌
tokens--;
retun true;
}
}
4、兩者區別
令牌桶里面裝載的是令牌,然后讓令牌去關聯到數據發送,常規漏桶里面裝載的是數據,令牌桶允許用戶的正常的持續突發量(Bc),就是一次就將桶里的令牌全部用盡的方式來支持續突發,而常規的漏桶則不允許用戶任何突發行。