php 实现网关限流
PHP 实现网关限流的方法
令牌桶算法实现
令牌桶算法是一种常用的限流方法,通过控制令牌的生成和消耗来实现限流。以下是一个简单的 PHP 实现:
class TokenBucket {
private $capacity;
private $tokens;
private $lastTime;
public function __construct($capacity) {
$this->capacity = $capacity;
$this->tokens = $capacity;
$this->lastTime = time();
}
public function consume($tokens = 1) {
$now = time();
$elapsed = $now - $this->lastTime;
$this->tokens = min($this->capacity, $this->tokens + $elapsed);
$this->lastTime = $now;
if ($this->tokens >= $tokens) {
$this->tokens -= $tokens;
return true;
}
return false;
}
}
// 使用示例
$bucket = new TokenBucket(10); // 每秒最多10个请求
if (!$bucket->consume()) {
http_response_code(429);
exit('Too Many Requests');
}
漏桶算法实现
漏桶算法以固定速率处理请求,超出容量的请求会被丢弃或排队。PHP 实现如下:
class LeakyBucket {
private $capacity;
private $rate;
private $water;
private $lastTime;
public function __construct($capacity, $rate) {
$this->capacity = $capacity;
$this->rate = $rate;
$this->water = 0;
$this->lastTime = time();
}
public function add() {
$now = time();
$leaked = ($now - $this->lastTime) * $this->rate;
$this->water = max(0, $this->water - $leaked);
$this->lastTime = $now;
if ($this->water < $this->capacity) {
$this->water++;
return true;
}
return false;
}
}
// 使用示例
$bucket = new LeakyBucket(10, 1); // 容量10,每秒漏出1个
if (!$bucket->add()) {
http_response_code(429);
exit('Rate Limit Exceeded');
}
Redis 分布式限流
对于分布式系统,可以使用 Redis 实现限流:
function checkRateLimit($key, $limit, $window) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$current = $redis->get($key);
if ($current && $current >= $limit) {
return false;
}
$redis->multi();
$redis->incr($key);
$redis->expire($key, $window);
$redis->exec();
return true;
}
// 使用示例
if (!checkRateLimit('user:123', 100, 60)) { // 每分钟100次
http_response_code(429);
exit('Rate Limit Exceeded');
}
Nginx 层限流
在网关层面可以使用 Nginx 的 limit_req 模块:
http {
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {
location /api/ {
limit_req zone=mylimit burst=20 nodelay;
proxy_pass http://backend;
}
}
}
中间件实现
在框架中可以使用中间件实现限流,例如 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);
}
}
限流策略选择建议
- 对于简单应用,可以使用 PHP 内存实现的令牌桶或漏桶算法
- 分布式系统推荐使用 Redis 实现
- 高性能场景建议在 Nginx 层实现限流
- 框架应用可以使用内置的限流中间件
每种方法都有其适用场景,应根据具体需求选择合适的限流策略。







