xp-forge / ratelimit
速率限制
v3.2.0
2024-03-24 13:13 UTC
Requires
- php: >=7.0.0
- xp-framework/core: ^12.0 | ^11.0 | ^10.0 | ^9.0 | ^8.0 | ^7.0
Requires (Dev)
- xp-framework/test: ^2.0 | ^1.0
README
速率限制可以用来限制物理或逻辑资源的访问速率,例如,为了防止资源被有意或无意过度使用。
限制使用
假设您不想每秒运行超过两个任务
use util\invoke\RateLimiting; $rateLimiter= new RateLimiting(2); foreach ($tasks as $task) { $rateLimiter->acquire(); // will wait if necessary $task->run(); }
限制带宽
您可以通过为每个字节获取许可来实现带宽节流
use util\invoke\{RateLimiting, Rate, Per}; $rateLimiter= new RateLimiting(new Rate(1000000, Per::$MINUTE)); while ($bytes= $source->read()) { $rateLimiter->acquire(strlen($bytes)); $target->write($bytes); }
限制用户速率
实现以下类似的过滤器
use web\{Filter, Error}; use util\invoke\{RateLimiting, Rate, Per}; class RateLimitingFilter implements Filter { private $rates, $rate, $timeout; public function __construct(KeyValueStorage $rates) { $this->rates= $rates; $this->rate= new Rate(5000, Per::$HOUR); $this->timeout= 0.2; } public function filter($request, $response, $invocation) { $remote= $request->header('Remote-Addr'); $limits= $this->rates->get($remote) ?: new RateLimiting($this->rate); $permitted= $limits->tryAcquiring(1, $this->timeout); $this->rates->put($remote, $limits); $response->header('X-RateLimit-Limit', $limits->rate()->value()); $response->header('X-RateLimit-Remaining', $limits->remaining()); $response->header('X-RateLimit-Reset', $limits->resetTime()); if (!$permitted) { throw new Error(429, 'Rate limit exceeded'); } return $invocation->proceed($request, $response); } }
进一步阅读
- RateLimiter - 发现Google Guava by Tomasz Nurkiewicz
- Guava的RateLimiter类 - 该项目就是受其启发。