我正在尝试调试PHP应用程序的一些奇怪行为。它正在运行Laravel 6+AWS SQS。该程序使用作业从VoIP提供商的API下载呼叫记录。API有一个很高的速率限制,即10req/分钟,所以我正在限制我这边的请求。作业配置为尝试使用retryUntil
方法在24小时内完成。但是,在4次尝试后,该作业将从队列中消失。它不会失败。作业的failed
方法永远不会被执行(我在其中放入了logging和Sentry::capture(。它不在failed_jobs表上。最后一条日志说";无法完成作业,正在重试。。。秒";,其正好在CCD_ 3呼叫之前。但是,该作业只是从队列中消失,再也不会执行。
我正在记录尝试次数、最大尝试次数、timeoutAt等。一切似乎都配置正确。以下是我的代码:
public function handle()
{
/** @var Track $track */
$track = Track::idOrUuId($this->trackId);
$this->logger->info('Downloading track', [
'trackId' => $track->getId(),
'attempt' => $this->attempts(),
'retryUntil' => $this->job->timeoutAt(),
'maxTries' => $this->job->maxTries(),
]);
$throttleKey = sprintf('track.download.%s', $track->getUser()->getTeamId());
if (!$this->rateLimiter->tooManyAttempts($throttleKey, self::MAX_ALLOWED_JOBS)) {
$this->downloadTrack($track);
$this->rateLimiter->hit($throttleKey, 60);
} else {
$delay = random_int(10, 100) + $this->rateLimiter->availableIn($throttleKey);
$this->logger->info('Throttling track download.', [
'trackId' => $track->getId(),
'delay' => $delay,
]);
$this->release($delay);
}
}
public function retryUntil(): DateTimeInterface
{
return now()->addHours(24);
}
public function failed(Exception $exception)
{
$this->logger->info('Job failed', ['exception' => $exception->getMessage()];
Sentry::captureException($exception);
}
我发现了这个问题,我将它发布在这里,供未来可能遇到困难的人使用。这一切都归结为一个简单的配置。在AWS SQS中,我正在处理的队列具有配置的DLQ
(死信队列(和设置为4的Maximum receives
。根据SQS文件
最大接收值确定消息何时发送到DLQ。如果消息的ReceiveCount超过队列的最大接收计数,Amazon SQS会将消息移动到关联的DLQ(带有其原始消息ID(。
由于这是一个基础配置,它会覆盖您可能传递给作业的任何Laravel参数。由于消息只是从队列中删除,因此处理作业实际上不会失败,因此不会执行failed
方法。