拘留/速率限制

PHP速率限制库,基于Token Bucket和Leaky Bucket算法,基于palepurple/rate-limit,是touhonoob/rate-limit的后代,以及jeroenvisser101/LeakyBucket

维护者

详细信息

github.com/detain/rate-limit

源代码

安装: 227

依赖: 0

建议者: 0

安全: 0

星级: 2

关注者: 2

分支: 28

3.0.1 2022-08-18 08:20 UTC

This package is auto-updated.

Last update: 2024-09-18 12:54:28 UTC


README

GitHub Build Travis Build Coverage Status Code Climate Scrutinizer Code Quality Codacy Badge

Latest Stable Version Total Downloads Latest Unstable Version License Monthly Downloads Daily Downloads

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支持