php实现限流
PHP 实现限流的方法
计数器法
计数器法是最简单的限流算法,通过统计单位时间内的请求次数来判断是否超过阈值。
class CounterLimiter {
private $limit;
private $interval;
private $count = 0;
private $lastResetTime;
public function __construct($limit, $interval) {
$this->limit = $limit;
$this->interval = $interval;
$this->lastResetTime = time();
}
public function allowRequest() {
$currentTime = time();
if ($currentTime - $this->lastResetTime > $this->interval) {
$this->count = 0;
$this->lastResetTime = $currentTime;
}
if ($this->count < $this->limit) {
$this->count++;
return true;
}
return false;
}
}
滑动窗口法
滑动窗口法是对计数器法的改进,可以更精确地控制单位时间内的请求量。

class SlidingWindowLimiter {
private $limit;
private $interval;
private $requests = [];
public function __construct($limit, $interval) {
$this->limit = $limit;
$this->interval = $interval;
}
public function allowRequest() {
$currentTime = time();
$this->requests[] = $currentTime;
while (!empty($this->requests) && $currentTime - $this->requests[0] > $this->interval) {
array_shift($this->requests);
}
return count($this->requests) <= $this->limit;
}
}
令牌桶算法
令牌桶算法允许突发流量,通过定期向桶中添加令牌来控制请求速率。

class TokenBucketLimiter {
private $capacity;
private $tokens;
private $rate;
private $lastTime;
public function __construct($capacity, $rate) {
$this->capacity = $capacity;
$this->tokens = $capacity;
$this->rate = $rate;
$this->lastTime = time();
}
public function allowRequest() {
$currentTime = time();
$elapsed = $currentTime - $this->lastTime;
$this->tokens = min($this->capacity, $this->tokens + $elapsed * $this->rate);
$this->lastTime = $currentTime;
if ($this->tokens >= 1) {
$this->tokens--;
return true;
}
return false;
}
}
Redis 实现分布式限流
在分布式环境中,可以使用 Redis 实现限流,确保多个服务节点之间的限流一致性。
class RedisLimiter {
private $redis;
private $key;
private $limit;
private $interval;
public function __construct($redis, $key, $limit, $interval) {
$this->redis = $redis;
$this->key = $key;
$this->limit = $limit;
$this->interval = $interval;
}
public function allowRequest() {
$currentTime = time();
$this->redis->zRemRangeByScore($this->key, 0, $currentTime - $this->interval);
$count = $this->redis->zCard($this->key);
if ($count < $this->limit) {
$this->redis->zAdd($this->key, $currentTime, uniqid());
return true;
}
return false;
}
}
使用框架中间件
在 Laravel 等框架中,可以使用中间件实现限流功能。
namespace App\Http\Middleware;
use Closure;
use Illuminate\Cache\RateLimiter;
use Symfony\Component\HttpFoundation\Response;
class ThrottleRequests {
protected $limiter;
public function __construct(RateLimiter $limiter) {
$this->limiter = $limiter;
}
public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1) {
$key = $request->ip();
if ($this->limiter->tooManyAttempts($key, $maxAttempts)) {
return new Response('Too Many Attempts', 429);
}
$this->limiter->hit($key, $decayMinutes * 60);
return $next($request);
}
}
以上方法可以根据实际需求选择适合的限流策略,单机环境下可以使用内存限流,分布式环境下建议使用 Redis 实现。






