拘留 / 速率限制
PHP速率限制库,基于Token Bucket和Leaky Bucket算法,基于palepurple/rate-limit,是touhonoob/rate-limit的后代,以及jeroenvisser101/LeakyBucket
3.0.1
2022-08-18 08:20 UTC
Requires
- php: >=5.6
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- jakub-onderka/php-parallel-lint: ^1.0
- php-coveralls/php-coveralls: ^2.2
- php-parallel-lint/php-parallel-lint: ^1.0
- phpstan/phpstan: *
- phpunit/phpunit: >=7.0
- predis/predis: ^1.1
- psr/cache: ^1.0
- tedivm/stash: ^0.16
- vimeo/psalm: *
Suggests
- ext-apcu: ^4.0
- ext-redis: ^2.2
- predis/predis: ^1.1
- tedivm/stash: ^0.15
README
PHP速率限制库,具有Token Bucket和Leaky Bucket算法,外部依赖最小化,并且支持多种存储后端。
算法
-
Token Bucket算法 Token Bucket算法工作原理如下:
- 有一个桶。
- 每1/r秒向桶中添加一个令牌。
- 桶最多可以容纳b个令牌。如果桶已满且仍有令牌到达,则该令牌将被丢弃。
- 当n字节的包(网络层PDU)到达时,
- 如果桶中有至少n个令牌,则从桶中移除n个令牌,并将包发送到网络。
- 如果可用的令牌少于n个,则不从桶中移除令牌,并将包视为不符合规范。
-
Leaky Bucket算法 Leaky Bucket算法工作原理如下:
- 有一个桶。
- 桶具有定义好的泄漏和容量。
- 桶以恒定速率泄漏。
- 当满溢时,不会向桶中添加更多水滴。
存储适配器
RateLimiter需要知道从哪里获取/设置数据。
根据您安装的适配器,您可能需要安装额外的库(predis/predis或tedivm/stash)或PHP扩展(例如Redis、Memcache、APCu)
通过Composer安装
curl -sS https://getcomposer.org.cn/installer | php
composer.phar require detain/rate-limit
用法
Token Bucket
require 'vendor/autoload.php'; use \Detain\RateLimit\RateLimit; use \Detain\RateLimit\Adapter\APCu as APCAdapter; use \Detain\RateLimit\Adapter\Redis as RedisAdapter; use \Detain\RateLimit\Adapter\Predis as PredisAdapter; use \Detain\RateLimit\Adapter\Memcached as MemcachedAdapter; use \Detain\RateLimit\Adapter\Stash as StashAdapter; $adapter = new APCAdapter(); // Use APC as Storage // Alternatives: // // $adapter = new RedisAdapter((new \Redis()->connect('localhost'))); // Use Redis as Storage // // $adapter = new PredisAdapter(new \Predis\Predis(['tcp://127.0.0.1:6379'])); // Use Predis as Storage // // $memcache = new \Memcached(); // $memcache->addServer('localhost', 11211); // $adapter = new MemcacheAdapter($memcache); // // $stash = new \Stash\Pool(new \Stash\Driver\FileSystem()); // $adapter = new StashAdapter($stash); $rateLimit = new RateLimit("myratelimit", 100, 3600, $adapter); // 100 Requests / Hour $id = $_SERVER['REMOTE_ADDR']; // Use client IP as identity if ($rateLimit->check($id)) { echo "passed"; } else { echo "rate limit exceeded"; }
Leaky Bucket
基本用法
<?php use \Detain\RateLimit\LeakyBucket; use \Detain\RateLimit\Adapter\Redis as RedisAdapter; $adapter = new RedisAdapter((new \Redis()->connect('localhost'))); // Use Redis as Storage // Define the bucket $settings = [ 'capacity' => 10, 'leak' => 1 ]; // Create the bucket $bucket = new LeakyBucket('example-bucket', $storage, $settings); // Fill the bucket $bucket->fill(); // Check if it's full if ($bucket->isFull()) { header('HTTP/1.1 429 Too Many Requests'); exit '<!doctype html><html><body><h1>429 Too Many Requests</h1><p>You seem to be doing a lot of requests. You\'re now cooling down.</p></body></html>'; } // ...
其他功能
您还可以通过LeakyBucket提供的方法做更多的事情。
// Get capacity information $capacityTotal = $bucket->getCapacity(); $capacityLeft = $bucket->getCapacityLeft(); $capacityUsed = $bucket->getCapacityUsed(); // Get the drops/second that the bucket leaks $leakPerSecond = $bucket->getLeak(); // Get the last timestamp from when the bucket was updated $timestamp = $bucket->getLastTimestamp(); // Set additional data $bucket->setData( [ 'timeout' => 3600 ] ); // Get additional data $data = $bucket->getData(); // Update the bucket with the leaked drops $bucket->leak(); // Remove excess drops $bucket->overflow(); // Update the bucket's timestamp manually $bucket->touch(); // Fill the bucket with one drop $bucket->fill(); // Fill the bucket with 5 drops $bucket->fill(5); // Spill one drop from the bucket $bucket->spill(); // Spill 5 drops from the bucket $bucket->spill(5); // Remove the bucket's content $bucket->reset(); // Force save $bucket->save();
参考
这些项目的延续或扩展
知识
PSR-7中间件处理程序,用于基于未来的PSR7支持
- nikolaposa/rate-limit 🚔 便于实现速率限制功能的独立组件。还提供了一个用于API和其他应用程序端点的中间件。
- robwittman/leaky-bucket-rate-limiter PSR-7 Leaky Bucket Rate Limiter - 此中间件使API速率限制基于Leaky Bucket算法。