为了处理大量的工作,我运行可变数量的队列工作者,具体取决于完成的工作量。我不想在完成我们认为合适的时间段内完成需要完成的工作之前运行更多的工人。
目前,我启动了5个守护程序队列工作程序用于测试目的,但是在生产中,这个数字可能介于25和25之间。 100名工人,可能更多。我理解在部署时,我必须首先通过使用php artisan down
将框架置于维护模式来停止队列工作,因为--daemon
标志导致框架仅在工作人员启动时加载,因此在工作重启之前,新代码在部署期间不会生效。
如果由于某种原因需要停止工作,我可以使用php artisan down
将应用程序置于维护模式,这将导致工作人员在完成当前工作(如果他们正在工作)工作后死亡。但是,有时我可能会在不将整个应用程序置于维护模式的情况下杀死工作人员。
是否有一种安全的方法可以阻止工人继续处理他们当前的工作,然后在不将整个应用程序置于维护模式的情况下死亡?
基本上我需要的是php artisan queue:stop
,其行为类似php artisan queue:restart
,但在作业完成后不会重新启动工作人员。
我在那里期待有一个类似php artisan queue:stop
的命令可以做到这一点,但似乎并非如此。
使用ps aux | grep php
我能够获得工作者的进程ID,并且我可以通过这种方式终止进程,但我不想在处理作业的过程中终止进程。
感谢。
答案 0 :(得分:4)
我们已经在我们的应用程序中实现了类似的东西 - 但它并不是Laravel本身内置的东西。您必须通过向if块添加另一个条件来编辑this file,以便它可以调用stop
函数。您可以通过在Worker
类中设置静态变量来执行此操作,无论何时运行您必须执行的自定义命令(即php artisan queue:pause
),或者通过在某处检查原子值(即将它设置在一些缓存中,如redis,memcached,APC甚至MySQL,尽管这意味着你将使用相同的自定义命令设置这个while循环的每个循环一个MySQL查询。
答案 1 :(得分:3)
当使用--daemon
标志时,当队列为空时,工作人员不应该退出。
我认为你要找的是in the documentation for queues.
php artisan queue:restart
命令将提示工作人员完成当前工作后重新启动。
答案 2 :(得分:0)
从Laravel 5.5开始,有一个名为Illuminate\Queue\Events\Looping
的事件从daemonShouldRun()
的主工作程序循环内的Illuminate\Queue\Worker
调用中触发。因此,如果您设置了一个侦听器来执行应处理作业检查,并返回false,则队列工作器将停止直到检查返回true。在下一次检查它之间有一个睡眠,您可以通过将--sleep <seconds>
传递到queue:work命令来进行自定义。
我目前正在部署过程中使用此技术来阻止在docker容器中运行的工作程序,因为要在其上运行建议的queue:restart
而不进行黑客入侵并不容易。
答案 3 :(得分:0)
我的Laravel是5.6。 你可以(杀死你的pid)不用担心失去工作 只需加载pcntl(extension)Laravel即可收听信号并安全退出
在下面显示零件来源(在./vendor/laravel/framework/src/Illuminate/Queue/Worker.php中):
protected function listenForSignals()
{
pcntl_async_signals(true);
pcntl_signal(SIGTERM, function () {
$this->shouldQuit = true;
});
pcntl_signal(SIGUSR2, function () {
$this->paused = true;
});
pcntl_signal(SIGCONT, function () {
$this->paused = false;
});
}
下面是我的测试
for($i=0; $i<100; $i++){
pcntl_async_signals(true);
pcntl_signal(SIGTERM, function () {
echo 'SIGTERM';
});
pcntl_signal(SIGUSR2, function () {
echo 'SIGUSR2';
});
pcntl_signal(SIGCONT, function () {
echo 'SIGCONT';
});
echo $i;
sleep(1);
}
您可以尝试杀死它