限流算法之漏桶和令牌桶

1.漏桶

漏桶主要目的是控制數據注入網絡的速率,平滑網絡上的突發流量。漏桶可以看做是一個帶有常量服務時間的單服務隊列,如果漏桶溢出,那麼數據包會被丟棄。

<?php
class SmoothWarmingUp {
	private $timeStamp;
	public $capacity;	//桶的總容量(爲了測試單位改爲每5秒容量)
	public $rate;		//流出速率(單位每百毫秒)
	public $token;		//當前容量
	
	public function __construct() {
		$this->timeStamp = $this->getMillisecond();
		$this->capacity = 30;
		$this->rate = 3;
	}
	
	public function grant() {
		$timeNow = $this->getMillisecond();
		$diff = floor (($timeNow - $this->timeStamp)/100);
		if($diff >= 50) {
			//清空這一秒當前容量
			$this->token = 0;
			$this->timeStamp = $timeNow;
		} else {
			$this->token = max(0, $this->token - $diff * $this->rate);
		}
		
		if(($this->token + 1) < $this->capacity) {
			//容器未滿,加入桶中
			$this->token += 1;
                        //桶中數據按照固定流出速率流出
			return true;
		} else {
			//容器滿了,拒絕
			return false;
		}
	}
	
	public function getMillisecond() {
		list($s1, $s2) = explode(' ', microtime());
		return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
	}
}

$bucket = new SmoothWarmingUp();
for($i = 0; $i < 150; $i++) {
	echo $i;
	var_dump($bucket->grant());
}

for($i = 0; $i < 150; $i++) {
	echo $i;
	var_dump($bucket->grant());
	sleep(1);
}

2.令牌桶

令牌桶算法原理是系統會以一個恆定的速率向桶中放令牌,如果請求需要被處理,則需要先從桶裏獲取一個令牌,當桶中沒有令牌時,拒絕服務。

<?php
class SmoothWarmingUp {
	private $timeStamp;
	public $capacity;	//允許的最大併發量(每5秒)
	public $rate;		//放入令牌速率(單位每百毫秒)
	public $token;		//桶中令牌數
	
	public function __construct() {
		$this->timeStamp = $this->getMillisecond();
		$this->capacity = 50;
		$this->token = 0;
		$this->rate = 3;
	}
	
	public function grant() {
		$timeNow = $this->getMillisecond();
		$diff = floor (($timeNow - $this->timeStamp)/100);
		$this->token = min($this->capacity, $diff * $this->rate);
		if($diff >= 50) {
			$this->timeStamp = $timeNow;
		}
		
		if($this->token > 0) {
			//桶中還有令牌,發放
			$this->token -= 1;
			
			return true;
		} else {
			//沒令牌拒絕
			return false;
		}
	}
	
	public function getMillisecond() {
		list($s1, $s2) = explode(' ', microtime());
		return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
	}
}

$bucket = new SmoothWarmingUp();
for($i = 0; $i < 150; $i++) {
	echo $i;
	var_dump($bucket->grant());
}

for($i = 0; $i < 150; $i++) {
	echo $i;
	var_dump($bucket->grant());
	sleep(1);
}

 

漏桶算法和令牌桶算法最明顯的區別是令牌桶算法允許流量有一定程度的突發。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章