有时要在服务器端控制每个IP单位时间内连接数,或在客户端限制对某个服务器单位时间内的请求数,可以使用以下算法:
1.Leaky Bucket漏桶算法
2.Token Bucket令牌桶算法
3.使用hash ttl计数
PHP实现的一个Token Bucket令牌桶算法,原理是计算上次请求时间到现在请求时间增加的令牌数,然后看令牌桶内是否有空余的令牌,每次请求后令牌减1,由于php变量生存期为脚本执行期,在应用中可将数据保存到共享内存为数据库:
<?php
class TokenBucket {
private $capacity;
private $tokens;
private $rate;
private $timestamp;
//rate为每秒限制连接数,同时初始桶大小为rate
public function __construct($rate) {
$this->capacity = $rate;
$this->tokens = $rate;
$this->rate = $rate;
$this->timestamp = time();
}
public function consume() {
//如果令牌少于1返回false
if (($tokens = $this->tokens()) < 1) {
return false;
}
//本次请求后令牌减1
$this->tokens--;
return true;
}
public function tokens() {
$now = time();
if ($this->tokens < $this->capacity) {
//计算上次请求时间到现在要增加的令牌数
$delta = $this->rate * ($now - $this->timestamp);
$this->tokens = min($this->capacity, $this->tokens + $delta);
}
//更新请求时间
$this->timestamp = $now;
return $this->tokens;
}
}
$tk = new TokenBucket(5, 5);
for ($i = 1; $i < 6; $i++) {
var_dump($tk->consume());
}
sleep(1);
for ($i = 1; $i < 6; $i++) {
var_dump($tk->consume());
}
?>
输出如下:
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(false)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(false)
标签:none