Laravel Redis 队列忽略节流
Laravel Redis Queue Ignoring Throttling
我正在使用 Laravel Horizon 和 Redis,我正在尝试限制它。我正在使用一个外部 API,它的速率限制为每分钟 100 个请求。我需要提出大约 700 个请求。我对其进行了设置,以便我添加到队列中的每个作业仅在作业本身中执行一个 API 调用。因此,如果我限制队列,我应该能够保持在限制范围内。出于某种原因,没有发生任何限制,而是通过队列(当然会触发许多 API 错误)。但是节流阀在本地工作,而不是在我的服务器上工作。
我最初试图根据 Laravel 的队列文档进行限制,但只能让它在本地工作,所以我转而尝试 Github 上的 laravel-queue-rate-limit 包。根据自述文件,我将以下内容添加到我的 queue.php
配置文件中:
'rateLimits' => [
'default' => [ // queue name
'allows' => 75, // 75 job
'every' => 60 // per 60 seconds
]
],
出于某种原因,当我在我的本地 Ubuntu 环境中 运行 时,节流正常工作,但它在我的服务器上不起作用(也 Ubuntu)。在服务器上,它只是吹过队列,就好像没有适当的限制一样。
我是不是做错了什么,或者有更好的方法来处理外部限速 API?
编辑 1:
config/horizon.php
'environments' => [
'production' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['default'],
'balance' => 'simple',
'processes' => 3,
'tries' => 100,
],
],
启动大多数作业的句柄之一:
public function handle()
{
$updatedPlayerIds = [];
foreach ($this->players as $player) {
$playerUpdate = Player::updateOrCreate(
[
'id' => $player['id'],
],
[
'faction_id' => $player['faction_id'],
'name' => $player['name'],
]
);
// Storing id's of records updated
$updatedPlayerIds[] = $playerUpdate->id;
// If it's a new player or the player was last updated awhile ago, then get new data!
if ($playerUpdate->wasRecentlyCreated ||
$playerUpdate->last_complete_update_at == null ||
Carbon::parse($playerUpdate->last_complete_update_at)->diffInHours(Carbon::now()) >= 6) {
Log::info("Updating '{$playerUpdate->name}' with new data", ['playerUpdate' => $playerUpdate]);
UpdatePlayer::dispatch($playerUpdate);
} else {
// Log::debug("Player data fresh, no update performed", ['playerUpdate' => $playerUpdate]);
}
}
//Delete any ID's that were not updated via the API
Player::where('faction_id', $this->faction->id)->whereNotIn('id', $updatedPlayerIds)->delete();
}
此外,这是我制作的粗略图表,试图说明我如何在短时间内生成多个作业 PHP 文件,尤其是像 updatePlayer()
这样的文件经常生成 700 次。
您提到的包 (laravel-queue-rate-limit) does not work well 看起来像 Horizon。您最好使用 Laravel 的内置方法。
在 Laravel 的队列中,添加 ->block(60)
以匹配 ->every(60)
以便默认超时不会启动并在 60 秒之前调用另一个回调。
Redis::throttle('torn-api')->allow(75)->every(60)->block(60)
此外,考虑将超时和最大重试值添加到 Horizon 的配置 (config/horizon.php)
。您还可以在作业本身中使用 failed
方法记录任何异常。参见 this。
在 Horizon 的配置中设置 retry_after
和 timeout
值。您在配置中的 retry_after
值应始终大于完成一项工作所需的时间。 timeout
值应该比 retry_after
值短几秒。 “这将确保处理给定工作的工人总是在重试工作之前被杀死。”请参阅文档中的 issue and this point。
我正在使用 Laravel Horizon 和 Redis,我正在尝试限制它。我正在使用一个外部 API,它的速率限制为每分钟 100 个请求。我需要提出大约 700 个请求。我对其进行了设置,以便我添加到队列中的每个作业仅在作业本身中执行一个 API 调用。因此,如果我限制队列,我应该能够保持在限制范围内。出于某种原因,没有发生任何限制,而是通过队列(当然会触发许多 API 错误)。但是节流阀在本地工作,而不是在我的服务器上工作。
我最初试图根据 Laravel 的队列文档进行限制,但只能让它在本地工作,所以我转而尝试 Github 上的 laravel-queue-rate-limit 包。根据自述文件,我将以下内容添加到我的 queue.php
配置文件中:
'rateLimits' => [
'default' => [ // queue name
'allows' => 75, // 75 job
'every' => 60 // per 60 seconds
]
],
出于某种原因,当我在我的本地 Ubuntu 环境中 运行 时,节流正常工作,但它在我的服务器上不起作用(也 Ubuntu)。在服务器上,它只是吹过队列,就好像没有适当的限制一样。
我是不是做错了什么,或者有更好的方法来处理外部限速 API?
编辑 1:
config/horizon.php
'environments' => [
'production' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['default'],
'balance' => 'simple',
'processes' => 3,
'tries' => 100,
],
],
启动大多数作业的句柄之一:
public function handle()
{
$updatedPlayerIds = [];
foreach ($this->players as $player) {
$playerUpdate = Player::updateOrCreate(
[
'id' => $player['id'],
],
[
'faction_id' => $player['faction_id'],
'name' => $player['name'],
]
);
// Storing id's of records updated
$updatedPlayerIds[] = $playerUpdate->id;
// If it's a new player or the player was last updated awhile ago, then get new data!
if ($playerUpdate->wasRecentlyCreated ||
$playerUpdate->last_complete_update_at == null ||
Carbon::parse($playerUpdate->last_complete_update_at)->diffInHours(Carbon::now()) >= 6) {
Log::info("Updating '{$playerUpdate->name}' with new data", ['playerUpdate' => $playerUpdate]);
UpdatePlayer::dispatch($playerUpdate);
} else {
// Log::debug("Player data fresh, no update performed", ['playerUpdate' => $playerUpdate]);
}
}
//Delete any ID's that were not updated via the API
Player::where('faction_id', $this->faction->id)->whereNotIn('id', $updatedPlayerIds)->delete();
}
此外,这是我制作的粗略图表,试图说明我如何在短时间内生成多个作业 PHP 文件,尤其是像 updatePlayer()
这样的文件经常生成 700 次。
您提到的包 (laravel-queue-rate-limit) does not work well 看起来像 Horizon。您最好使用 Laravel 的内置方法。
在 Laravel 的队列中,添加 ->block(60)
以匹配 ->every(60)
以便默认超时不会启动并在 60 秒之前调用另一个回调。
Redis::throttle('torn-api')->allow(75)->every(60)->block(60)
此外,考虑将超时和最大重试值添加到 Horizon 的配置 (config/horizon.php)
。您还可以在作业本身中使用 failed
方法记录任何异常。参见 this。
在 Horizon 的配置中设置 retry_after
和 timeout
值。您在配置中的 retry_after
值应始终大于完成一项工作所需的时间。 timeout
值应该比 retry_after
值短几秒。 “这将确保处理给定工作的工人总是在重试工作之前被杀死。”请参阅文档中的 issue and this point。