PHP中的速率限制:请求限制完全指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

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)

通用

推荐