nimbly/throttler

一个与框架无关的速率限制器。

1.1 2021-01-14 22:22 UTC

This package is auto-updated.

Last update: 2024-09-15 06:34:11 UTC


README

Latest Stable Version Build Status License

一个与框架无关的请求速率限制器。

描述

Throttler可以在任何您喜欢的数据点上实施速率限制:IP地址、用户ID、API密钥或任何您可以访问的唯一标识信息。

安装

composer require nimbly/throttler

用法

存储适配器

您需要一个地方来跟踪点击计数器 - 缓存、数据库或任何其他。创建一个存储适配器实例并将其传递给Throttler。有关适配器的完整列表,请参阅下面的可用存储适配器部分。

$storageAdapter = new Throttler\Adapters\Redis(
    new Predis\Client('tcp://localhost:6379')
);

Throttler

通过传递存储适配器实例来实例化Throttler。

$throttler = new Throttler($storageAdapter);

构造函数选项

您可以将键值对选项数组作为构造函数的第二个参数传递。

$throttler = new Throttler($storageAdapter, ['key' => 'value']);

支持选项

  • prefix 应用到所有键和传递给存储适配器的前缀。默认为Throttler\

方法

hit(string $id, int $limit, int $decay) : boolean

记录在速率限制器上的点击,增加速率限制计数器。在成功时返回true,在失败时返回false

  • id 是此请求源的唯一ID。此值可以是任何您想要的字符串:IP地址、用户ID等。
  • limit 是在由 decay 定义的时间段内允许的总请求数。
  • decay 是允许的时间段(以秒为单位)。

此示例允许每个IP地址在60秒时间段内允许120个请求。

if( $throttler->hit($request->ipAddress(), 120, 60) === false ){
    throw new TooManyRequestsHttpException(60, 'Slow it down man!');
}

check(string $id) : int

检查(但不增加)给定ID的当前速率限制计数器。

if( $throttler->check($request->user->id) >= $warningThreshold ){
    $response = $response->withHeader("X-Rate-Limit", "Warning");
}

中间件

将速率限制器添加到您的中间件(您正在使用中间件,对吧?)

class ThrottleRequest implements SomeMiddlewareLibrary
{
    public function handle(Request $request, $next)
    {
        $storageAdapter = new Throttler\Adapters\Redis(
            new Predis\Client('tcp://localhost:6379')
        );

        $throttler = new Throttler($storageAdapter);

        if( $throttler->hit($request->ipAddress(), 120, 60) === false ){
            throw new TooManyRequestsHttpException(60, 'Slow it down man!');
        }

        return $next($request);
    }
}

可用存储适配器

以下列表提供了“开箱即用”的存储适配器

Redis

需要通过Predis库,该库可在predis/predis上找到。

$redisAdapter = new Throttler\Adapters\Redis(
    new Predis\Client("tcp://localhost:6379")
);

$throttler = new Throttler($redisAdapter);

数据库

数据库适配器可以使用任何PDO兼容数据库来持久化速率限制器数据。只需将此表添加到您的数据库

CREATE TABLE throttler
(
    key VARCHAR(64) PRIMARY KEY,
    hits INTEGER UNSIGNED NOT NULL DEFAULT 1,
    expires_at INTEGER UNSIGNED NOT NULL
)
$databaseAdapter = new Throttler\Adapters\Database(
    new PDO("mysql:dbname=myapp;host=localhost", "username", "password")
);

$throttler = new Throttler($databaseAdapter);

您还可以自定义Throttler将使用的列以及垃圾回收的机会

  • table 要使用的表名。默认为throttler
  • key 键列名。列类型必须是字符串或varchar。默认为key
  • hits 点击列名。列类型必须是整数。默认为hits
  • expires_at 过期列名。列类型必须是整数(UNIX时间戳)。默认为expires_at
  • gc_chance 垃圾回收运行的百分比机会。小于1的值表示它将永远不会运行。大于99的值表示它将在每个调用时运行。默认为5
$databaseAdapter = new Throttler\Adapters\Database(
    new PDO("mysql:dbname=myapp;host=localhost", "username", "password"),
    [
        "table" => "limiter",
        "key" => "id",
        "hits" => "value",
        "expires_at" => "ttl",
        "gc_chance" => 20,
    ]
);

$throttler = new Throttler($databaseAdapter);

APCu

APCu是一个内存中的PHP缓存,需要通过大多数Linux包管理器提供的PECL APCu库。

$apcuAdapter = new Throttler\Adapters\Apcu;

$throttler = new Throttler($apcuAdapter);

内存

内存适配器仅在内存中维护其节流器,不会在HTTP或CLI请求之间持久化其数据。此适配器非常适合测试或其他特殊用例。只有当您了解自己在做什么时才使用此适配器。

$memoryAdapter = new Throttler\Adapters\Memory;

$throttler = new Throttler($memoryAdapter);

自定义存储适配器

提供了一个 Throttler\StorageAdapter 接口,以便您可以创建自己的适配器,用于您想要的任何持久化引擎。它必须实现两个方法

get(string $key) : int

返回给定键的当前计数器,如果键不存在则返回0。

increment(string $key, int $decay) : int

增加给定键的计数器。如果键不存在,则必须创建它并将计数器设置为1,同时将计数器设置在 $decay 秒后过期。返回计数器值。

use Nimbly\Throttler\StorageAdapter;

class MyStorageAdapter implements StorageAdapter
{
    public function get(string $key): int
    {
        // Get $key from storage engine.
    }

    public function increment(string $key, int $decay): int
    {
        // Increment $key on storage engine and return new value.
    }
}