spatie / laravel-rate-limited-job-middleware
可以限制作业执行频率的中间件
Requires
- php: ^8.0
- artisansdk/ratelimiter: ^1.1
- illuminate/cache: ^8.0|^9.0|^10.0|^11.0
- illuminate/redis: ^8.0|^9.0|^10.0|^11.0
Requires (Dev)
- mockery/mockery: ^1.4.1
- orchestra/testbench: ^6.23|^7.0|^8.0|^9.0
- pestphp/pest: ^1.21|^2.34
- phpunit/phpunit: ^9.5|^10.5
- spatie/pest-plugin-test-time: ^1.0|^2.0
- symfony/var-dumper: ^5.4|^6.0|^7.0
README
本包包含一个作业中间件,可以限制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)。有关更多信息,请参阅许可文件。