【问题标题】:Laravel Queue with Supervisor not working with Multiple WebsitesLaravel 队列与主管不与多个网站一起工作
【发布时间】:2019-08-20 14:09:16
【问题描述】:

将运行 Laravel 队列的单个网站添加到 Supervisor 时,延迟的作业会按应有的方式处理。

当我将另一个网站添加到 Supervisor 时,不会为任何网站/队列处理延迟的作业。

我已尝试重新读取、重新加载和重新启动服务。 supervisord.log 显示所有正在运行的进程,但未触发作业。

如果我停止除 1 名工作人员之外的所有工作人员,则队列工作。

Laravel 5.7

监督者 3.3.1

redis-cli 3.2.6

Debian/Nginx

sudo nano /etc/supervisor/conf.d/website-a-worker.conf
[program:website-a-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/website.a/artisan queue:work redis --sleep=3 --tries=3
autostart=true
autorestart=true
#user=laravel
numprocs=8
autostart=true
autorestart=true
stdout_logfile=/var/www/website.a/storage/logs/worker.log
stderr_logfile=/var/www/website.a/storage/logs/worker.err.log
sudo nano /etc/supervisor/conf.d/website-b-worker.conf
[program:website-b-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/website.b/artisan queue:work redis --sleep=3 --tries=3
autostart=true
autorestart=true
#user=laravel
numprocs=8
autostart=true
autorestart=true
stdout_logfile=/var/www/website.b/storage/logs/worker.log
stderr_logfile=/var/www/website.b/storage/logs/worker.err.log
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start website-a-worker:*
sudo supervisorctl start website-b-worker:*

// config/queue.php
...
'redis' => [
            'driver' => 'redis',
            'connection' => 'default',
            'queue' => 'default',
            'retry_after' => 600,
            'block_for' => null,
        ],
...
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class SomeJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function handle()
    {
       \Log::info('This only gets triggered if 1 supervisor worker is running.');
    }
}
> sudo service supervisor restart
> cd /var/www/website.a
> php artisan tinker

>>> App\Jobs\SomeJob::dispatch()->delay(1);
# Job does not get triggered
>>> exit

作业永远不会被触发。 但是,如果我停止 website.b 的主管,website.a 将处理作业。

> sudo supervisorctl stop website-b-worker:*
website-b-worker:website-b-worker_02: stopped
website-b-worker:website-b-worker_03: stopped
website-b-worker:website-b-worker_00: stopped
website-b-worker:website-b-worker_01: stopped
website-b-worker:website-b-worker_06: stopped
website-b-worker:website-b-worker_07: stopped
website-b-worker:website-b-worker_04: stopped
website-b-worker:website-b-worker_05: stopped

> php artisan tinker

>>> App\Jobs\SomeJob::dispatch()->delay(1);
# Job gets triggered!

如何运行多个工作器(每个网站至少 1 个)?

【问题讨论】:

  • 我从未尝试过使用多个网站进行监督。但是对于您有很多网站,numprocs 值是否可以?
  • 在答案中查看我的编辑,这比在每个作业上放置$this-&gt;onQueue() 更好,并在队列配置中设置队列名称自动:'queue' =&gt; 'websiteAQueue',

标签: laravel supervisord


【解决方案1】:

我已经将 Supervisor 与 Laravel 和 Redis 一起使用,但一次只能用于 1 个网站。但是我做了一些研究,发现你可以在 Laravel https://laravel.com/docs/5.8/queues#connections-vs-queues 中指定队列进程的名称。

Laravel Job 有一个 setter 方法 onQueue() 来指定队列的名称。 laravel 文档示例:

Job::dispatch()->onQueue('emails');

但在您的代码SomeJob 中,您可以直接使用$this-&gt;onQueue('queue_name') 调用它;你的代码可以是:

<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class SomeJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function handle()
    {
        // on website a
        $this->onQueue('websiteAQueue');
        \Log::info('This only gets triggered if 1 supervisor worker is running.');
    }
}

在网站 A 的主管进程中,指定队列参数为 websiteAQueue

[program:website-a-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/website.a/artisan queue:work redis --queue=WebsiteAQueue --sleep=3 --tries=3
autostart=true
autorestart=true
#user=laravel
numprocs=8
autostart=true
autorestart=true
stdout_logfile=/var/www/website.a/storage/logs/worker.log
stderr_logfile=/var/www/website.a/storage/logs/worker.err.log

这样,当 Laravel 发送 Job 时,它会将其发送到指定的队列,而不是它找到的默认队列。

编辑------------------------

或者更好的是,您可以为每个网站配置使用不同的队列名称:

// Website A : config/queue.php
...
'redis' => [
            'driver' => 'redis',
            'connection' => 'default',
            'queue' => 'websiteAQueue',
            'retry_after' => 600,
            'block_for' => null,
        ],
...

这样所有队列都会自动发送到websiteAQueue,因此您不必在每个作业上都使用$this-&gt;onQueue()

【讨论】:

  • 是的,我最终使用了第二个选项 - 编辑 config/queue.php 并更改每个站点的队列名称并在 .conf 中指定队列名称。
猜你喜欢
  • 2020-03-17
  • 2017-03-28
  • 2018-03-15
  • 1970-01-01
  • 1970-01-01
  • 2021-05-22
  • 2019-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多