Laravel队列处理超时错误

76

我正在使用 Laravel 并运行排队的作业,命令为 php artisan queue:listen。其中一个作业非常复杂且需要很长时间,因此我收到以下错误提示:

[Symfony\Component\Process\Exception\ProcessTimedOutException]                                                                                                                                                                              
The process ""/usr/local/Cellar/php55/5.5.14/bin/php" artisan queue:work  
--queue="QUEUE_URL" --delay=0 --memory=128 --sleep=3 --tries=0" 
exceeded the timeout of 60 seconds.

我知道我可以使用任意高的超时值来运行queue:listen,但这并不理想,因为如果某个进程实际上无响应,我确实希望它超时。我尝试在作业调用的函数内定期调用set_time_limit(60),但那没有解决我的问题。

我在网上找到了一个线程,提到了Symfony\Component\Process\Process->setTimeout(null),但我不知道如何访问该进程对象,或者这是否会解决问题。

任何帮助将不胜感激。


2
你尝试过使用 "php artisan queue:listen --timeout=120" 命令吗?如果你只需要延长队列运行的时间,我认为没有必要重新发明轮子。不过,如果你需要超过5分钟的时间,你可能需要发布处理队列作业的实际方法。 - michael.schuett
就像我之前所说的,queue:listen --timeout={number} 是可行的,但是我正在运行的特定任务可能需要几秒钟到一小时甚至更长时间,我不想设置一个过高的超时值。 - Will Durney
什么导致了方差?这是您的应用程序结构问题。为了解决这个问题,我们需要查看代码,以便在您需要解析大量数据的情况下更好地进行优化。这需要拆分成更多的作业。 - michael.schuett
1
引起问题的特定工作是在大量输入上运行的O(n^2)算法。我们对输入大小施加了硬限制以使其合理,但事实上它只是一个可能需要很长时间的过程。我们正在使用作业队列在后台处理它,完成后,它会向我们的API发出http请求以指示已完成。有没有更好的方法来处理这样的事情?将处理拆分成许多作业?由于它是需要在数据上运行的单个算法,因此似乎过于复杂。我不明白为什么set_time_limit不起作用。 - Will Durney
我会将其重写为另一种语言的微服务,使其公开一个HTTP API并通过HTTP将数据发布到它,然后它可以在完成后通知您现有的应用程序。 Golang或Node听起来更合适。 PHP确实不适合处理这种类型的繁重工作。 - AndrewMcLagan
4个回答

131

在我的设置中,添加--timeout=0就可以解决问题。

更新: 整个命令应为php artisan queue:listen --timeout=0


34
给其他用户的提示:将超时时间设置为0可能会导致“不可见”的无限循环,这可能是危险的。建议设置一个“合理”的超时时间,比如120秒。 - rap-2-h
有其他的方法吗?@rap-2-h 的观点是正确的,但我的问题是,在我的脚本中,我正在进行非常复杂的工作,可能需要超过24小时才能完成。有什么解决方案吗? - Rizh
2
@Rizh 那我会说你的设计有问题。你不应该依赖于需要运行很长时间才能执行某些操作的进程。将其分解成更小的组件。 - ankush981
谢谢,这正是我需要正常运行xdebug的东西。不知何故,脚本总是崩溃... - Mārtiņš Briedis
1
我已经搜索了源代码和Laravel文档,没有发现任何说明0超时值意味着无限制的内容。我们曾经认为它是这样的,但实际上出现了问题,脚本在默认超时时间内超时并没有到达无限制超时。有谁能指出在源代码或文档中支持这个理论的地方吗?https://laravel.com/docs/8.x/queues#timeout - Dean Whitehouse

16

在投入了许多时间后,我找到了解决方案

将以下代码行添加到Job类中,您的作业将不会超时运行,即使您将作业放入cron表条目中

public $timeout = 0;

4

这是 Laravel v5.3 中已知的 bug:

你应该升级到 v5.5 以解决此问题。

另一种方法是按照 这里 的说明修改源代码。


2
“黑客攻击源代码”从来不是一个好主意,但由于这个问题已经超过三年并且有一个被接受的答案,你的观点在哪里呢? - Nico Haase
是的!黑客攻击源代码从来不是一个好主意,但这比使用“--timeout=0”更好。 - Mostafa Lavaei
为什么黑客他人的源代码比在调用时设置专门为此目的创建的选项更好? - Nico Haase
2
因为--timeout=0可能会导致无限进程。这并不是真正的黑客行为,只是在v5.5中进行的升级。 - Mostafa Lavaei

2
队列主要用于那些需要很长时间才能完成的请求,比如大量发送邮件、导入数据等后台任务。它还可以提高我们的Web应用程序性能。如果我们不设置超时时间,则默认为60秒。如果我们将超时时间设置为0,则表示我们设置了无限超时时间,请求将一直运行直到完成。要设置超时时间,我们需要运行以下命令:php artisan queue:listen --timeout=0。 以下是官方文档的参考链接:https://laravel.com/docs/8.x/queues

文档中没有提到60秒是默认超时时间,但在示例中提到了60秒。他们是否意味着这是默认值? - otaku
@otaku 是的,默認值為60秒。 - Maduka Jayalath
我猜那不是60,在我的情况下,由于max_execution_time的限制,它是30。 - Samuel Aiala Ferreira

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接