如何使Laravel Queue系统在服务器上运行

zer*_*nes 50 crontab laravel artisan

我最近设置了一个Laravel Queue系统.基础是cronjob调用一个命令,它将作业添加到队列中并调用第二个发送电子邮件的命令.

当我进入我的服务器并运行php artisan队列时,系统工作:listen,但是如果我关闭我的终端,则监听器关闭,作业堆叠起来并排队,直到我重新进入并再次运行监听.

什么是让我的队列系统在后台运行而不需要通过ssh保持我的连接打开的最佳方法?

我尝试运行php artisan queue:work --daemon,它完成了队列中的作业,但当我关闭终端时,它关闭了连接和后台进程.

Ben*_*rne 60

运行

nohup php artisan queue:work --daemon &
Run Code Online (Sandbox Code Playgroud)

注销时会阻止命令退出.

尾随&符号(&)导致进程在后台启动,因此您可以继续使用shell,而不必等到脚本完成.

nohup

nohup - 运行一个免于挂断的命令,输出为非tty

这将把信息输出到运行命令的目录中名为nohup.out的文件.如果您对输出不感兴趣,可以将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 &
Run Code Online (Sandbox Code Playgroud)

但是你也应该使用像Supervisord这样的东西来确保服务保持运行并在崩溃/失败后重新启动.

  • 首先我需要:http://stackoverflow.com/a/29292637/470749然后`nohup php artisan queue:work --daemon> storage/logs/laravel.log&`为我工作.注意:如果你想杀死nohup守护进程,你需要先运行类似`ps -ef | grep artisan`的东西来发现它的PID.然后你可以运行`kill [pid]`http://stackoverflow.com/q/17385794/470749 (7认同)
  • 这是一个糟糕的解决方案,因为一旦你发出一个队列:重置工作人员就会死掉,并且你没有重新启动机制,只需使用supervisord,生成2个工作人员,当你的工作量很大时,你就会像黄金一样好。附带说明一下,每次更改代码时,您都需要重新生成新的工作人员。 (4认同)
  • @z900collector 答案明确说你应该使用像 Supervisord 这样的东西,而且总是这样做。 (2认同)

Man*_*kar 22

你应该使用linux supervisor

安装很简单,在Ubuntu上我可以使用以下命令安装它:

apt-get install supervisor
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

对于每个进程,您应该创建一个新的进程配置文件.使用此配置,侦听器将重试每个作业3次.如果监听程序失败或系统重新启动,Supervisor也会重新启动监听程序.

  • 更多说明在这里,https://www.digitalocean.com/community/tutorials/how-to-install-and-manage-supervisor-on-ubuntu-and-debian-vps (2认同)
  • 值得注意的是,这个答案也是 Laravel 记录的做事方式:https://laravel.com/docs/5.6/queues#supervisor-configuration (2认同)

zer*_*nes 12

命令

nohup php artisan queue:work --daemon &
Run Code Online (Sandbox Code Playgroud)

是正确的,它将允许进程在关闭SSH连接后继续; 但是,这只是一个短期的解决方案.重新启动服务器或任何问题导致进程停止后,您将需要返回并再次运行该命令.当发生这种情况时,你永远不知道.它可能发生在星期五晚上,因此最好实施长期解决方案.

我最终切换到Supervisord,这可以安装在Ubuntu上一样简单

sudo apt-get install supervisor 
Run Code Online (Sandbox Code Playgroud)

对于AWS-AMI或RedHat用户,您可以按照我在此问题中列出的说明进行操作:

在AWS AMI Linux服务器上设置Supervisord

  • 该答案仅适用于Ubuntu用户,我的回答链接到一个单独的问题,如何在基于RedHat的发行版上进行设置.此外,我回答了Dev 15 2016,其他答案仅针对Ubuntu用户,于2017年6月发布. (2认同)

Sau*_*try 8

安装主管

sudo apt-get install supervisor
Run Code Online (Sandbox Code Playgroud)

配置主管

第 1 步:转到/etc/supervisor/conf.d目录

cd /etc/supervisor/conf.d
Run Code Online (Sandbox Code Playgroud)

第 2 步:创建一个将侦听队列的工作文件laravel-worker.conf

sudo nano laravel-worker.conf
Run Code Online (Sandbox Code Playgroud)

*注意:现在假设您的 Laravel 应用程序在/var/www/html目录中

project folder is : /var/www/html/LaravelApp
Run Code Online (Sandbox Code Playgroud)

第 3 步:将以下代码粘贴到laravel-worker.conf并保存文件

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/LaravelApp/artisan queue:listen redis --queue=default --sleep=3 --tries=3 
autostart=true
autorestart=true
user=root
numprocs=8
redirect_stderr=true
stdout_logfile= /var/www/html/LaravelApp/storage/logs/worker.log
Run Code Online (Sandbox Code Playgroud)

*注意:这里假设您使用redis进行队列连接

在 .env 文件中 QUEUE_CONNECTION=redis

command=php /var/www/html/LaravelApp/artisan queue:listen redis
Run Code Online (Sandbox Code Playgroud)

如果您使用其他连接,则一般语法为:

command= php [project_folder_path]/artisan queue:listen [connection_name]
Run Code Online (Sandbox Code Playgroud)

[connection_name] 可以是syncdatabasebeanstalkdsqsredis 中的任何一个

第 4 步:创建一个工作文件laravel-schedule.conf,它将每 1 分钟(60 秒)运行一次artisan schedule:run命令(*您可以根据需要进行更改)

[program:laravel-schedule]
process_name=%(program_name)s_%(process_num)02d
command=/bin/bash -c 'while true; do date && php /var/www/html/LaravelApp/artisan schedule:run; sleep 60; done'
autostart=true
autorestart=true
numprocs=1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
Run Code Online (Sandbox Code Playgroud)

第 5 步:启动主管:运行以下命令

sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start all
Run Code Online (Sandbox Code Playgroud)

*注意:每当您对任何配置.conf文件进行更改时,请运行上述步骤 5 的命令

额外有用的信息:

  • 停止所有 supervisorctl 进程: sudo supervisorctl stop all
  • 重新启动所有 supervisorctl 进程: sudo supervisorctl restart all

有用的链接:

https://laravel.com/docs/5.8/queues#running-the-queue-worker

http://supervisord.org/index.html


Har*_*osh 7

来自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'); // 5.1
        $processIsQueueListener = ! empty($process); // 5.6 - see comments

        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 $!'; // 5.1
        $command = 'php-cli ' . base_path() . '/artisan queue:work --timeout=60 --sleep=5 --tries=3 > /dev/null & echo $!'; // 5.6 - see comments
        $pid = exec($command);

        return $pid;
    }
}
Run Code Online (Sandbox Code Playgroud)


dew*_*ald 6

对于那些已经在他们的生产环境中运行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
Run Code Online (Sandbox Code Playgroud)

我在开发和设置 NodeJS 中使用 Vagrant,这个过程只使用内联 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
Run Code Online (Sandbox Code Playgroud)


Lal*_*hel 6

1)sudo apt install supervisor

sudo apt-get install supervisor
Run Code Online (Sandbox Code Playgroud)

2)cd /etc/supervisor/conf.d 3)在内部创建新文件

sudo vim queue-worker.conf
Run Code Online (Sandbox Code Playgroud)

文件内容

[program:email-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/laravelproject/artisan queue:work
autostart=true
autorestart=true
user=root
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/html/laravelproject/storage/logs/supervisord.log
Run Code Online (Sandbox Code Playgroud)

4)sudo supervisorctl reread

运行此命令时获取输出queue-worker:available

5)sudo supervisorctl update

运行此命令时,获取输出queue-worker:added进程组

其他命令

1)sudo supervisorctl reload

运行此命令时获取输出重新启动主管

2)sudo service supervisor restart


Lah*_*hah 5

使用 pm2

我使用pm2(高级,Node.js 的生产流程管理器)运行 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.
Run Code Online (Sandbox Code Playgroud)

现在运行:

> sudo pm2 start process.yml
Run Code Online (Sandbox Code Playgroud)

检查 pm2 的更多选项和功能


eRe*_*Inc 5

由于这是一个特定于 Laravel 的问题,我想我会建议一个特定于 Lravel 的答案。由于您已经在此服务器上使用 cronjobs,因此我建议您将 shell 命令设置为重复的 cronjob,以始终验证工作线程是否正在运行。您可以将 shell 命令设置为通过服务器上的 cron 本地运行,也可以使用 Laravel 控制台内核来管理命令并添加逻辑,例如检查是否已经有一个工作线程在运行,如果没有,则继续并重新启动它。

根据您需要运行命令的频率,您可以每周执行一次,甚至每分钟一次。这将使您能够确保您的工作人员持续运行,而无需向您的服务器(例如 Supervisor)添加任何开销。如果您信任它,向像主管这样的第 3 方包授予权限是可以的,但是如果您可以避免需要依赖它,您可能需要考虑这种方法。

使用它来执行您想要的操作的一个示例是每小时运行一个 cronjob。它将从自定义 Laravel 控制台命令中按顺序执行以下命令:

\Artisan::call('队列:重新启动');

\Artisan::call('队列:工作 --daemon');

请注意,这适用于较旧版本的 Laravel(最高 5.3),但我尚未在较新版本上进行测试。


小智 5

最好的方法是 PM2(高级,Node.js 的生产流程管理器),您可以监控您的队列并查看它们的日志。

在您的项目目录中使用以下命令,运行 queue worker :

pm2 start artisan --name laravel-worker --interpreter php -- queue:work --daemon
Run Code Online (Sandbox Code Playgroud)


Sna*_*rak 5

对于使用systemd作为初始化服务的系统,您可以使用以下服务,使其适应您的项目(在 /etc/systemd/system/queue-handler.service 上创建):

[Unit]
Description = Queue Handler - Project
After = network-online.target, mysql.service

[Service]
User = www-data
Type = simple
WorkingDirectory=/var/www/project
ExecStart = /usr/bin/php /var/www/project/artisan queue:work --tries=3
Restart = on-failure
RestartSec=5s
RestartPreventExitStatus = 255

[Install]
WantedBy = multi-user.target
Run Code Online (Sandbox Code Playgroud)

重新加载配置并在启动时启用它:

[Unit]
Description = Queue Handler - Project
After = network-online.target, mysql.service

[Service]
User = www-data
Type = simple
WorkingDirectory=/var/www/project
ExecStart = /usr/bin/php /var/www/project/artisan queue:work --tries=3
Restart = on-failure
RestartSec=5s
RestartPreventExitStatus = 255

[Install]
WantedBy = multi-user.target
Run Code Online (Sandbox Code Playgroud)


Kra*_*ray 5

根据您的环境及其配置功能,有多种方法可以给这只猫剥皮。有些位于共享主机上,有些具有whm访问权限......

更直接和可维护的方式是:

在你的内核文件中添加$schedule->command('queue:work')->everyFiveMinutes()->withoutOverlapping();到您的计划方法。

这将每五分钟运行一次队列工作命令。

/**
 * Define the application's command schedule.
 *
 * @param Schedule $schedule
 * @return void
 */
protected function schedule(Schedule $schedule)
{
    $schedule->command('queue:work')->everyFiveMinutes()->withoutOverlapping();
}
Run Code Online (Sandbox Code Playgroud)

请参阅 laravel 文档 - https://laravel.com/docs/9.x/scheduling#defining-schedules