PHP中的速率限制:API保护与负载优化
速率限制(请求速度限制)是任何PHP Web应用程序(尤其是公共API)的关键机制。它可以防止滥用、抵御DDoS攻击、降低服务器负载,并确保用户之间资源的公平分配。本文将详细解析在PHP中实现速率限制的流行库和工具。
速率限制的主要算法
在选择库之前,了解基本算法非常重要:
- 令牌桶 — 最灵活的算法。桶中包含N个令牌,每个请求消耗一个令牌。令牌以设定的速率恢复。
- 漏桶 — 请求以恒定速率处理。多余的请求被丢弃或排队。
- 固定窗口 — 在固定时间间隔内(例如60秒)计数请求。简单,但可能在窗口边界处允许峰值负载。
- 滑动窗口 — 更精确的算法,在浮动时间窗口内统计请求。使用带有时间戳的日志或计数器。
PHP中流行的速率限制库
1. Symfony Rate Limiter (symfony/rate-limiter)
Symfony的官方组件,也可作为独立库使用。支持所有主要算法:令牌桶、固定窗口、滑动窗口。非常适合Symfony或Laravel项目。
use Symfony\\Component\\RateLimiter\\RateLimiterFactory;use Symfony\\Component\\RateLimiter\\Storage\\InMemoryStorage;
$factory = new RateLimiterFactory([ 'id' => 'api', 'policy' => 'token_bucket', 'limit' => 100, 'rate' => ['interval' => '1 minute'],], new InMemoryStorage());
$limiter = $factory->create('user_123');
if ($limiter->consume(1)->isAccepted()) { // 处理请求} else { // 返回429 Too Many Requests header('HTTP/1.1 429 Too Many Requests'); echo json_encode(['error' => 'Rate limit exceeded']);}2. nikic/FastRoute 配合中间件速率限制
适用于无框架项目的轻量级解决方案。使用PHP实现的令牌桶,并存储在Redis或Memcached中。
class RateLimitMiddleware { private $redis; private $maxRequests = 100; private $window = 60; // 秒
public function handle($request, $next) { $key = 'rate_limit:' . $_SERVER['REMOTE_ADDR']; $current = $this->redis->incr($key); if ($current === 1) { $this->redis->expire($key, $this->window); }
if ($current > $this->maxRequests) { return new Response('Too Many Requests', 429); }
return $next($request); }}3. Laravel Rate Limiter(内置)
Laravel的速率限制内置于核心中。使用Redis或缓存。支持命名限制器和按用户分段。
// 在RouteServiceProvider中use Illuminate\\Cache\\RateLimiting\\Limit;use Illuminate\\Http\\Request;
protected function configureRateLimiting(){ RateLimiter::for('api', function (Request $request) { return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); });}
// 在控制器中public function index(){ $executed = RateLimiter::attempt( 'send-message:'.$user->id, $perMinute = 5, function() { // 发送消息 } ); if (! $executed) { return response('Too Many Attempts.', 429); }}4. PHP RateLimit (php-rateLimit/php-rateLimit)
通用