spatie/laravel-rate-limited-job-middleware

可以限制作业执行频率的中间件

2.7.0 2024-09-07 09:22 UTC

README

Latest Version on Packagist run-tests Total Downloads

本包包含一个作业中间件,可以限制Laravel应用程序中作业的执行频率。

支持我们

我们在创建一流的开放式软件包上投入了大量资源。您可以通过购买我们的付费产品之一来支持我们。

我们非常感谢您从家乡寄给我们明信片,并说明您正在使用我们的哪个包。您可以在我们的联系页面上找到我们的地址。我们将发布所有收到的明信片在我们的虚拟明信片墙上

安装

您可以通过composer安装此包

composer require spatie/laravel-rate-limited-job-middleware

用法

默认情况下,中间件每秒只允许执行5个作业。任何不允许执行的作业将释放5秒。

要应用中间件,只需将Spatie\RateLimitedMiddleware\RateLimited添加到您的作业中间件中。

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Spatie\RateLimitedMiddleware\RateLimited;

class TestJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable;

    public function handle()
    {
        // your job logic
    }

    public function middleware()
    {
        return [new RateLimited()];
    }
}

配置尝试次数

当使用频率限制时,您的作业尝试次数可能难以预测。与其使用固定的尝试次数,不如使用基于时间的尝试次数

您可以将此添加到您的作业类中

/*
 * Determine the time at which the job should timeout.
 *
 */
public function retryUntil() :  \DateTime
{
    return now()->addDay();
}

自定义行为

您可以自定义所有行为。以下是一个示例,其中中间件允许在60秒内最多执行30个作业。不允许执行的作业将释放90秒。

// in your job

public function middleware()
{
    $rateLimitedMiddleware = (new RateLimited())
        ->allow(30)
        ->everySeconds(60)
        ->releaseAfterSeconds(90);

    return [$rateLimitedMiddleware];
}

实现指数退避

远程服务(如API)通常有频率限制或其他服务器错误响应。在这些情况下,在再次尝试之前增加我们的延迟是有意义的。您可以使用releaseAfter方法替换为releaseAfterBackoff($this->attempts()以使用默认的速率限制器间隔5秒。否则,您可以连锁调用releaseAfter来调整退避间隔。

示例:releaseAfterOneMinute()

// in your job

/**
 * Attempt 1: Release after 60 seconds
 * Attempt 2: Release after 180 seconds
 * Attempt 3: Release after 420 seconds
 * Attempt 4: Release after 900 seconds
 */
public function middleware()
{
    $rateLimitedMiddleware = (new RateLimited())
        ->allow(30)
        ->everySeconds(60)
        ->releaseAfterOneMinute()
        ->releaseAfterBackoff($this->attempts());

    return [$rateLimitedMiddleware];
}

示例:releaseAfterSeconds()

// in your job

/**
 * Attempt 1: Release after 5 seconds
 * Attempt 2: Release after 15 seconds
 * Attempt 3: Release after 35 seconds
 * Attempt 4: Release after 75 seconds
 */
public function middleware()
{
    $rateLimitedMiddleware = (new RateLimited())
        ->allow(30)
        ->everySeconds(60)
        ->releaseAfterSeconds(5)
        ->releaseAfterBackoff($this->attempts());

    return [$rateLimitedMiddleware];
}

示例:自定义退避速率

releaseAfterBackoff()接受速率乘数作为第二个参数。默认情况下,乘数为2。

以下是一个将速率设置为3的示例。您会注意到,随着尝试次数的增加,2速率与3速率之间的差异变得非常明显。

// in your job

/**
 * Attempt 1: Release after 5 seconds
 * Attempt 2: Release after 20 seconds
 * Attempt 3: Release after 65 seconds
 * Attempt 4: Release after 200 seconds
 */
public function middleware()
{
    $rateLimitedMiddleware = (new RateLimited())
        ->allow(30)
        ->everySeconds(60)
        ->releaseAfterBackoff($this->attempts(), 3);

    return [$rateLimitedMiddleware];
}

不释放作业

如果您不想在频率限制时重试作业,可以使用dontRelease()方法。这在您有定期运行的作业且不关心作业被跳过的情况下非常有用。

public function middleware()
{
    $rateLimitedMiddleware = (new RateLimited())
        ->allow(30)
        ->everySeconds(60)
        ->dontRelease();

    return [$rateLimitedMiddleware];
}

自定义Redis

默认情况下,中间件将使用默认的Redis连接。

在Redis中默认将使用的键将是创建中间件实例的类的名称。在大多数情况下,这将是在其中应用中间件的作业的名称。如果这不是您期望的,您可以使用key方法来自定义它。

以下是一个使用自定义连接和自定义键的示例。

// in your job

public function middleware()
{
    $rateLimitedMiddleware = (new RateLimited())
        ->connectionName('my-custom-connection')
        ->key('my-custom-key');

    return [$rateLimitedMiddleware];
}

条件性应用中间件

如果您想有条件地应用中间件,可以使用 enabled 方法。它接受一个布尔值,用于确定是否对您的作业进行速率限制。

您还可以将一个 Closure 传递给 enabled。如果它评估为真值,则中间件将启用。

以下是一个愚蠢的例子,其中速率限制仅在1月份激活。

// in your job

public function middleware()
{
    $shouldRateLimitJobs = Carbon::now()->month === 1;

    $rateLimitedMiddleware = (new RateLimited())
        ->enabled($shouldRateLimitJobs);

    return [$rateLimitedMiddleware];
}

可用方法。

这些方法可以在中间件上调用。它们的名称应该具有自解释性。

  • allow(int $allowedNumberOfJobsInTimeSpan)
  • everySecond(int $timespanInSeconds = 1)
  • everySeconds(int $timespanInSeconds)
  • everyMinute(int $timespanInMinutes = 1)
  • everyMinutes(int $timespanInMinutes)
  • releaseAfterOneSecond()
  • releaseAfterSeconds(int $releaseInSeconds)
  • releaseAfterOneMinute()
  • releaseAfterMinutes(int $releaseInMinutes)
  • releaseAfterRandomSeconds(int $min = 1, int $max = 10)

可用事件。

  • 当超出速率限制时触发 \Spatie\RateLimitedMiddleware\Events\LimitExceeded

测试

composer test

变更日志

有关最近更改的更多信息,请参阅变更日志

贡献

有关详细信息,请参阅贡献指南

安全性

如果您发现有关安全的错误,请通过邮件 security@spatie.be 而不是使用问题跟踪器。

明信片

您可以使用这个包,但如果它进入您的生产环境,我们非常感谢您从家乡寄给我们一张明信片,注明您正在使用我们哪个包。

我们的地址是:Spatie,Kruikstraat 22,2018 安特卫普,比利时。

我们将所有收到的明信片发布在我们的公司网站上

致谢

此代码在很大程度上基于Laravel文档中找到的速率限制示例

许可

MIT许可(MIT)。有关更多信息,请参阅许可文件