php Laravel Artisan CLI 安全地停止守护进程队列工作者

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30060526/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 21:30:56  来源:igfitidea点击:

Laravel Artisan CLI safely stop daemon queue workers

phplaravelqueuedaemonartisan

提问by Vigs

In order to process large numbers of jobs, I run a variable number of queue workers depending on howmuch work there is to complete. I don't want to run more workers than are necessary to complete the work that needs to be done in a time period that we deem appropriate.

为了处理大量作业,我运行了可变数量的队列工作器,具体取决于要完成的工作量。我不想在我们认为合适的时间段内运行过多的工人来完成需要完成的工作。

At the moment, I start 5 daemon queue workers for testing purposes, however in production this number could be between 25 & 100 workers, possibly more. I understand that when deploying, I have to stop the queue workers by first placing the framework in maintenance mode by using php artisan down, because the --daemonflag causes the framework to only load when the worker starts up, hence new code would not take affect during the deploy until the worker restarts.

目前,为了测试目的,我启动了 5 个守护进程队列工作器,但是在生产中,这个数字可能在 25 到 100 个工作器之间,可能更多。我知道在部署时,我必须首先使用 using 将框架置于维护模式来停止队列工作人员php artisan down,因为该--daemon标志导致框架仅在工作人员启动时加载,因此新代码在部署期间不会生效,直到工人重新启动。

If i needed to stop the workers for some reason, I could put the application in maintenance mode using php artisan downwhich will cause the workers to die once they have finished processing their current job (if they are working one). However, there may be times where I want to kill the workers without putting the whole application in maintenance mode.

如果我出于某种原因需要停止工作人员,我可以将应用程序置于维护模式,使用php artisan down这将导致工作人员在完成当前工作(如果他们正在工作)后死亡。但是,有时我想在不将整个应用程序置于维护模式的情况下杀死工作人员。

Is there a safe way to stop the workers in a way where they will continue processing their current job and then die without placing the whole application in maintenance mode?

有没有一种安全的方法来阻止工作人员继续处理他们当前的工作,然后在不将整个应用程序置于维护模式的情况下死亡?

Essentially what I need is a php artisan queue:stop, which behaves like php artisan queue:restart, but does not restart the worker once the job is done.

基本上我需要的是一个php artisan queue:stop,它的行为类似于php artisan queue:restart,但一旦工作完成就不会重新启动工作程序。

I was expecing there to be a like php artisan queue:stopcommand that would do this, but that doesn't seem to be the case.

我期待有一个类似的php artisan queue:stop命令可以做到这一点,但似乎并非如此。

Using ps aux | grep phpI am able to get the process id's for the workers, and I could kill the processes that way, but I don't want to kill the process in the middle of it working on a job.

使用ps aux | grep php我能够获取工作人员的进程 ID,我可以通过这种方式终止进程,但我不想在执行工作的过程中终止该进程。

Thanks.

谢谢。

采纳答案by Nikko

We've implemented something like this in our application - but it was not something that was built-in to Laravel itself. You would have to edit this file, by adding another condition to the if-block so that it would call the stopfunction. You can do this by either setting a static variable in the Workerclass that gets changed whenever you run a custom command that you'll have to make (i.e. php artisan queue:pause) or by checking an atomic value somewhere (i.e. set it in some cache like redis, memcached, APC or even MySQL, though this would mean you'll have one MySQL query for every cycle of this while-loop) that you set using the same custom command.

我们已经在我们的应用程序中实现了类似的东西 - 但它不是 Laravel 本身内置的东西。您必须通过向 if 块添加另一个条件来编辑此文件,以便它调用该stop函数。您可以通过在Worker类中设置一个静态变量来做到这一点,无论何时运行您必须执行的自定义命令(即php artisan queue:pause)或通过检查某处的原子值(即,将其设置在某些缓存中,如 redis、memcached 、APC 甚至 MySQL,尽管这意味着您将使用相同的自定义命令设置的此 while 循环的每个周期都有一个 MySQL 查询。

回答by Deinumite

When using the --daemonflag workers shouldn't quit when the queue is empty.

使用--daemon标志时,当队列为空时,工作人员不应退出。

I think what you are looking for is in the documentation for queues.

我认为您正在寻找的是队列文档中的内容。

The php artisan queue:restartcommand will prompt the workers to restart after they are done their current job.

php artisan queue:restart命令将提示工作人员在完成当前工作后重新启动。

回答by alexkb

Since Laravel 5.5 there is an event called Illuminate\Queue\Events\Loopingthat gets fired from the daemonShouldRun()call inside the main worker loop of Illuminate\Queue\Worker. So if you setup a listener to do your should process jobscheck, and return false then the queue worker(s) will stop until the check returns true. There's a sleep between the next time it checks it which you can customise by passing --sleep <seconds>to the queue:work command.

由于Laravel 5.5有一个叫做事件Illuminate\Queue\Events\Looping,但未通过解雇daemonShouldRun()的工人主循环中调用Illuminate\Queue\Worker。因此,如果您设置了一个侦听器来执行应处理作业检查并返回 false,那么队列工作器将停止,直到检查返回 true。在下一次检查它之间有一个睡眠时间,您可以通过传递--sleep <seconds>给 queue:work 命令来自定义它。

I'm currently using this technique during deployments to stop workers which run inside docker containers, as it's not so easy to run the suggested queue:restarton them without hacking around.

我目前在部署期间使用这种技术来阻止在 docker 容器内运行的工作人员,因为queue:restart在不进行黑客攻击的情况下在它们上运行建议并不是那么容易。

回答by Zuo Zou

my Laravel is 5.6. you can (kill your pid) don't worry lose your work just load pcntl(extension) Laravel can listen to the signal and safe exit

我的 Laravel 是 5.6。你可以(杀死你的pid)不要担心失去你的工作,只需加载pcntl(扩展)Laravel可以监听信号并安全退出

show part source below(in ./vendor/laravel/framework/src/Illuminate/Queue/Worker.php):

在下面显示部分源代码(在 ./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;
    });
}

And my test below:

我的测试如下:

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);
 }

you can try to kill it

你可以试着杀死它