Как сохранить систему очереди Laravel запущенной на сервере



Недавно я установил систему очередей Laravel. Суть в том, что cronjob вызывает команду, которая добавляет задания в очередь, и вызывает вторую команду, которая отправляет электронное письмо.

Система работает, когда я подключаюсь по ssh к своему серверу и запускаю php artisan queue: listen, но если я закрываю свой терминал, прослушиватель выключается, и задания стекаются и сидят в очереди, пока я не вернусь по ssh и не запущу listen снова.

Как лучше всего поддерживать работу моей системы очередей в фоновом режиме без необходимости сохранять мой подключение через SSH?

Я попытался запустить php artisan queue:work --daemon, и он выполнил задания в очереди, но когда я закрыл свой терминал, он закрыл соединение и фоновый процесс.

114   9  

9 ответов:

Бег

nohup php artisan queue:work --daemon &

Предотвратит выход команды при выходе из системы.

Завершающий амперсанд ( & ) вызывает запуск процесса в фоновом режиме, поэтому вы можете продолжать использовать оболочку и не ждать завершения сценария.

См. nohup

Nohup-выполнить команду, невосприимчивую к зависаниям, с выводом в не-tty

Это выведет информацию в файл под названием nohup.в каталоге, где выполняется команда. Если у вас нет интереса к выходу, который вы можете перенаправить stdout и stderr в /dev/null, или аналогично вы можете вывести его в свой обычный журнал laravel. Например

nohup php artisan queue:work --daemon > /dev/null 2>&1 &

nohup php artisan queue:work --daemon > app/storage/logs/laravel.log &

Но вы также должны использовать что-то вроде Supervisord, чтобы гарантировать, что служба остается запущенной и перезапускается после сбоев/сбоев.

Вы должны использовать linux супервайзер

Установка проста и на Ubuntu я могу установить его с помощью следующей команды:

apt-get install supervisor

Файлы конфигурации супервизора находятся в файле/etc / supervisor / conf.D каталог.

[program:email-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/laravel-example/artisan queue:work redis --queue=emailqueue --sleep=3 --tries=3
autostart=true
autorestart=true
user=forge
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/laravel-example//storage/logs/supervisord.log

Для каждого процесса необходимо создать новый файл конфигурации процесса. При такой конфигурации прослушиватель будет повторять каждое задание 3 раза. Также Супервизор перезапустит прослушиватель, если он выйдет из строя или если система перезапустится.

Команда

nohup php artisan queue:work --daemon &

Было правильно, это позволило бы продолжить процесс после закрытия соединения SSH; однако, это только краткосрочное исправление. Как только ваш сервер будет перезагружен или любая проблема приведет к остановке процесса, вам нужно будет вернуться и снова запустить команду. Когда это происходит, вы никогда не знаете. Это может произойти в пятницу вечером, поэтому лучше реализовать долгосрочное решение.

Я в конечном итоге переключился на Supervisord, это может быть установлено на Ubuntu как легко как

sudo apt-get install supervisor 

Для пользователей AWS-AMI или RedHat вы можете следовать набору инструкций, которые я описал в этом вопросе:

Настройка супервайзера на сервере AWS AMI Linux

Что делать, если вы начинаете прослушивание внутри экрана? Смотрите здесь: http://aperiodic.net/screen/quick_reference Тогда, даже если вы выйдете из системы, экран будет по-прежнему активен и запущен. Хотя не знаю, почему демонизация не работает.

Для тех, кто уже запускает NodeJS в своих производственных средах. Я использую PM2 для управления процессами приложений.

# install
npm install -g pm2

# in project dir with your CI or dev setup tool 
# --name gives task a name so that you can later manage it
# -- delimits arguments that get passed to the script
pm2 start artisan --interpreter php --name queue-worker -- queue:work --daemon

Я использую Vagrant в разработке и настройке NodeJS, и этот процесс использует только встроенные скрипты vagrant.

Когда вы используете PM2 в разработке, вы можете использовать один из многих наблюдателей для управления перезапуском. Просто запустите pm2 restart queue-worker, Когда вы берете изменение. В производстве я не рекомендую этот подход, скорее выберу инструмент сборки, который может следовать этому процесс.

# 1. stop pm task to ensure that no unexpected behaviour occurs during build
pm2 stop queue-worker
# 2. do your build tasks
...
# 3. restart queue so that it loads the new code
pm2 restart queue-worker

Поскольку это был вопрос, специфичный для Ларавеля, я решил предложить ответ, специфичный для Лравеля. Поскольку вы уже используете cronjobs на этом сервере, я бы рекомендовал вам настроить команду shell как повторяющуюся cronjob, чтобы всегда проверять, что рабочий процесс запущен. Вы можете либо настроить команду shell для запуска через cron на вашем сервере, либо вы можете использовать ядро консоли Laravel для управления командой и добавления логики, например, проверить, есть ли у вас уже рабочий бежать и, если нет, идти вперед и запустить его обратно.

В зависимости от того, как часто вам нужно выполнять свою команду, вы можете делать это нечасто, например раз в неделю или даже раз в минуту. Это даст вам возможность убедиться, что ваши работники постоянно работают, без необходимости добавлять какие-либо накладные расходы на ваш сервер, такие как супервайзер. Предоставление разрешений стороннему пакету, такому как supervisor, нормально, если Вы доверяете ему, но если вы можете избежать необходимости полагаться на него, вы можете рассмотреть вместо этого-такой подход.

Примером использования этого для выполнения того, что вы хотите, было бы иметь cronjob, который выполняется каждый час. Он выполнит следующее в последовательном порядке из пользовательской команды консоли Laravel:

\Artisan:: call ('queue:restart');

\Artisan:: call ('queue:work --daemon');

Обратите внимание, что это относится к старым версиям Laravel (до 5.3), но я не тестировал на более новых версиях.

Из https://gist.github.com/ivanvermeyen/b72061c5d70c61e86875

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class EnsureQueueListenerIsRunning extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'queue:checkup';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Ensure that the queue listener is running.';

    /**
     * Create a new command instance.
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return void
     */
    public function handle()
    {
        if ( ! $this->isQueueListenerRunning()) {
            $this->comment('Queue listener is being started.');
            $pid = $this->startQueueListener();
            $this->saveQueueListenerPID($pid);
        }

        $this->comment('Queue listener is running.');
    }

    /**
     * Check if the queue listener is running.
     *
     * @return bool
     */
    private function isQueueListenerRunning()
    {
        if ( ! $pid = $this->getLastQueueListenerPID()) {
            return false;
        }

        $process = exec("ps -p $pid -opid=,cmd=");
        $processIsQueueListener = str_contains($process, 'queue:listen');

        return $processIsQueueListener;
    }

    /**
     * Get any existing queue listener PID.
     *
     * @return bool|string
     */
    private function getLastQueueListenerPID()
    {
        if ( ! file_exists(__DIR__ . '/queue.pid')) {
            return false;
        }

        return file_get_contents(__DIR__ . '/queue.pid');
    }

    /**
     * Save the queue listener PID to a file.
     *
     * @param $pid
     *
     * @return void
     */
    private function saveQueueListenerPID($pid)
    {
        file_put_contents(__DIR__ . '/queue.pid', $pid);
    }

    /**
     * Start the queue listener.
     *
     * @return int
     */
    private function startQueueListener()
    {
        $command = 'php-cli ' . base_path() . '/artisan queue:listen --timeout=60 --sleep=5 --tries=3 > /dev/null & echo $!';
        $pid = exec($command);

        return $pid;
    }
}

Вы можете использовать инструмент monit. он очень мал и полезен для любого типа управления процессами и мониторинга.

После загрузки двоичного пакета из по этой ссылке, Вы можете извлечь его в папку на вашей системе, а затем скопировать два файла из пакета в вашу систему, чтобы установить его:

cd /path/to/monit/folder
cp ./bin/monit /usr/sbin/monit
cp ./conf/monitrc /etc/monitrc  

Теперь отредактируйте /etc/monitrc базу по вашим потребностям( reference doc). затем создайте файл управленияinit , чтобы включить monit при запуске. теперь начните монить вот так:

initctl reload-configuration
start monit

Использование pm2

У меня был скрипт JS, работающий с pm2 (Advanced, production process manager for Node.js) который был единственным, которым я управлял. Но теперь, когда у меня есть еще один процесс, чтобы продолжать работать.

Я создал process.yml для запуска обоих с помощью одной команды. Проверьте, что первый из них будет работать php artisan queue: listen

# process.yml at /var/www/ which is root dir of the project
apps:
  # Run php artisan queue:listen to execute queue job
  - script    : 'artisan'
    name      : 'artisan-queue-listen'
    cwd       : '/var/www/'
    args      : 'queue:listen' # or queue:work
    interpreter : 'php'

  # same way add any other script if any.

Теперь запускаем:

> sudo pm2 start process.yml

Проверьте дополнительные опции и функции pm2

    Ничего не найдено.

Добавить ответ:
Отменить.