Laravel Artisan CLI safely stop daemon queue workers

前端 未结 4 2199
刺人心
刺人心 2021-01-01 18:03

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 ar

相关标签:
4条回答
  • 2021-01-01 18:19

    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

    show part source below(in ./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

    0 讨论(0)
  • 2021-01-01 18:23

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

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

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

    0 讨论(0)
  • 2021-01-01 18:32

    Since Laravel 5.5 there is an event called Illuminate\Queue\Events\Looping that 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 jobs check, 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.

    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:restart on them without hacking around.

    0 讨论(0)
  • 2021-01-01 18:36

    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 stop function. You can do this by either setting a static variable in the Worker class 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.

    0 讨论(0)
提交回复
热议问题