2016-09-07 4 views
0

В настоящее время я работаю над проектом, в котором я отправляю электронные письма в очередь. Однако я задаюсь вопросом, что было бы «лучшим способом» для запуска слушателя очереди. Прямо сейчас я знаю только о способе nohup.«Лучший способ» для запуска Laravel queue listen

Однако, используя nohup, похоже, что слушатель очереди больше не входит в приложение. Это похоже на использование планировщика, чтобы сделать ваши cronjobs частью приложения.

Есть ли другие способы прослушивания очереди и какими будут ваши предпочтения?

+0

Я достиг этого, написав задачу типа слушателя процесса, которую я планировал запускать каждую минуту. Что это значит, проверьте, работает ли очередь с помощью 'pgrep', и запускает ее, если обнаруживает, что она не запущена. – Jonathon

+0

@Jonathon Задача как в cronjob? У меня также была эта идея в моей голове, добавляя «queue: listen» в мой график laravel для запуска каждый день, но добавляя 'withoutOverlapping()'. Он хотел бы посмотреть: '$ schedule-> command ('queue: listen') -> daily() -> withoutOverlapping();'. –

+1

Да, я создал консольную команду 'App \ Console \ Commands \ QueueProcessListener'. Затем я добавил его в «Kernel.php», чтобы сделать его доступным для Artisan, и в конце концов добавил его в метод расписания Kernel, чтобы он запускался каждые 5 минут: '$ schedule-> command ('queue-process- listener ') -> everyFiveMinutes(); ' – Jonathon

ответ

3

Вот что я писал для достижения этой цели:

приложение/Console/Команды/QueueProcessListener.php

<?php 

namespace App\Console\Commands; 

use Illuminate\Console\Command; 

class QueueProcessListener extends Command 
{ 
    /** 
    * The name of the command/process we want to monitor. This string will be used both to check to see if the process 
    * is currently running and to spawn it (The arguments are appended to it). 
    * 
    * @var string 
    */ 
    protected $command = 'php artisan queue:listen'; 

    /** 
    * The arguments to pass to the process when spawning it. 
    * 
    * @var string 
    */ 
    protected $arguments = '--tries=3'; 

    /** 
    * The signature of the console command. We use the signature when running it through Artisan: php artisan $signature 
    * 
    * @var string 
    */ 
    protected $signature = 'queue-process-listener'; 

    /** 
    * The console command description. 
    * 
    * @var string 
    */ 
    protected $description = 'Monitor the queue listener process to ensure it is always running.'; 

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

    /** 
    * Execute the console command. 
    * 
    * @return mixed 
    */ 
    public function handle() 
    { 
     if (!$this->isProcessRunning($this->command)) { 
      $this->info("Starting queue listener."); 
      $this->executeShellCommand($this->command, $this->arguments, true); 
     } else { 
      $this->info("Queue listener is running."); 
     } 
    } 

    /** 
    * Execute a shell command, with the provided arguments, and optionally in the background. Commands that are not run 
    * in the background will return their output/response. 
    * 
    * @param $command 
    * @param string $arguments 
    * @param bool $background 
    * @return string 
    */ 
    public function executeShellCommand($command, $arguments = '', $background = false) 
    { 
     $command = trim($command); 
     if (!is_string($command) || empty($command)) { 
      return null; 
     } 

     $arguments = trim($arguments); 

     $cmd = trim($command . ' ' . $arguments) . ($background ? ' > /dev/null 2>/dev/null &' : ''); 
     return shell_exec($cmd); 
    } 

    /** 
    * Check if a process is running using pgrep. 
    * 
    * @param $process 
    * @return bool 
    */ 
    public function isProcessRunning($process) 
    { 
     $output = $this->executeShellCommand('pgrep -f "' . $process . '"'); 

     return !empty(trim($output)); 
    } 
} 

приложение/Console/Kernel.php

<?php 

namespace App\Console; 

use Illuminate\Console\Scheduling\Schedule; 
use Illuminate\Foundation\Console\Kernel as ConsoleKernel; 

class Kernel extends ConsoleKernel 
{ 
    /** 
    * The Artisan commands provided by your application. 
    * 
    * @var array 
    */ 
    protected $commands = [ 
     Commands\QueueProcessListener::class 
    ]; 

    /** 
    * Define the application's command schedule. 
    * 
    * @param \Illuminate\Console\Scheduling\Schedule $schedule 
    * @return void 
    */ 
    protected function schedule(Schedule $schedule) 
    { 
     // Schedule my process listener to run every 5 minutes. 
     $schedule->command('queue-process-listener')->everyFiveMinutes(); 
    } 
} 
+0

Спасибо, я думаю, я сделаю это, как вы сказали. Разве это не '$ schedule-> command ('queue: listen') -> daily() -> withoutOverlapp ing()' недостаточно? Поскольку это уже команда, которую можно вызвать и выполнить. –

+0

Прохладный. Проблема с этим заключается в том, что если слушатель очереди по какой-то причине останавливается в течение дня, он не запускается снова до следующего дня. С другой стороны, если он не останавливается в течение дня, вы рискуете запустить несколько слушателей очереди (если вы запустите команду в фоновом режиме с помощью «nohup» или '&' и т. Д.). Если вы выполняете команду 'queue: listen' напрямую, она не завершит выполнение вовремя, чтобы другие запланированные вами команды также запускались слишком, чтобы вы эффективно блокировали планировщик. – Jonathon

+0

Спасибо за ваш ответ. Забудьте 'daily()' или 'everyMinute()'. Используя 'withoutOverlapp ing()' вы предотвращаете его выполнение во время работы, верно? Или вы говорите, что планировщик будет ставить в очередь/стекать эти команды, даже если 'afterOverlapp ing()' используется для выполнения после того, как предыдущий закончен?А также вы говорите, что планировщик не асинхронный (он не может выполнять более одного за раз)? –

0

В документации вам точно сказано, как это сделать: https://laravel.com/docs/5.3/queues#supervisor-configuration

Я не уверен, что вы подразумеваете под этим, не являясь «частью приложения». Крон и фоновые рабочие процессы являются стандартной частью любой архитектуры серверного масштаба. Нет ничего плохого в их использовании.

Вы также должны избегать того, что предлагает ответ Джонатона, который в основном пишет ваши собственные supervisord в php. Что делать, если ваш сервер перезагружается? Для этой проблемы есть проверенные временем решения, которые уже давно разрабатываются и поддерживаются сообществом linux - вы действительно должны их использовать.