【发布时间】:2020-06-28 01:42:40
【问题描述】:
我正在使用 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 次。
【问题讨论】:
-
可以尝试将另一个键值对添加到
default数组 -block => 60吗?这可能是一个超时问题,在 3 秒后开始超时,并且立即调用另一个回调。 -
此外,上述软件包似乎不适用于 Horizon。使用 Laravel 的队列可能会更好。在 Laravel 的队列中添加到
Redis::throttle('key' )-->block(60)。 -
@Qumber 添加阻塞看起来已经修复它!我还换回了您提到的正常 Laravel 节流。无论如何,绝对更喜欢使用内置方法。
-
@Qumber 但是现在的问题似乎是他们经常只是在队列中坐了很长一段时间。我添加了一个应用此限制的中间件:
Redis::throttle('torn-api')->allow(75)->every(60)->block(60)。我试图只允许每 60 秒运行 75 个作业。 -
@Qumber 太好了,我认为它现在已修复。因为我假设你会想再次获得这个赏金,所以我将列出我最终改变的整体。 queue.php
retry_after设置为 70 在 horizon.php 中,waits.redis:default更改为 65,timeout更改为 60(在环境部分中)。我还删除了我的 supervisord 队列侦听器上的各种标志,以便只使用配置值。同样在我的RateLimited中间件中,我添加了->block(60),就像你提到的那样。我换回了常规节流而不是使用包。
标签: php laravel redis throttling task-queue