laravel佇列之Supervisor守護程式

她來聽我的演唱會發表於2020-12-24

前言

眾所周知,佇列的開啟為:php artisan queue:work,但是一旦關閉命令視窗佇列執行就關閉。因此官方推薦Supervisor。具體安裝配置使用教程可以參考官方文件
但是本著兼聽則明的原則,還有沒有其他可行的方式呢?於是查到一些資料,根據這篇文章:laravel佇列常駐執行問題的說法,還可以通過執行php artisan queue:work --daemon
看到這裡,我不禁拍案而起,大呼一聲“妙啊”,但是根據另外一篇文章laravel佇列常駐執行問題裡一個大佬說的:
“只是放到後臺執行而已,如果佇列出現致命錯誤,佇列必然掛彩,唯一的解決方法就是通過程式守護的方式實現重啟(supervisord)。只要supervisord程式存在,你的佇列就能永久的常駐程式。另外,supervisord貌似只支援linux”
然後通過查閱資料發現:

  • queue:work 預設只執行一次佇列請求, 當請求執行完成後就終止;
  • queue:listen 監聽佇列請求, 只要執行著, 就能一直接受請求, 除非手動終止;
  • queue:work --daemonlisten 一樣, 只要執行著, 就能一直接受請求, 不一樣的地方是在這個執行模式下, 當新的請求到來的時候, 不重新載入整個框架, 而是直接 fire 動作.
    能看出來, queue:work --daemon 是最高階的, 一般推薦使用這個來處理佇列監聽.

    注意: 使用 queue:work --daemon , 當更新程式碼的時候, 需要停止, 然後重新啟動, 這樣才能把修改的程式碼應用上.

綜合上述也就是說平時使用沒啥問題,但是遇到致命錯誤,佇列會掛掉,但是如果使用Supervisor,佇列掛了,會重新開啟。於是決定來跳這個坑。

開始

根據文件,各種安裝步驟省略,但是在開啟的時候遇到很多問題。
問題:

然後查閱以後發現了這篇文章:使用 Supervisor 管理 Laravel 佇列程式,發現了是在/etc/supervisord/conf.d中的配置檔案中指向的Log檔案許可權不夠,以及配置的問題。
laravel-work.conf配置檔案:

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
//指向的是需要執行的專案的佇列,等同於進入/home/vagrant/code/dcat目錄再執行:
//php artisan queue:work redis --sleep=3 --tries=3,原配置中redis為sqs,這個是
//佇列的連線,你用什麼佇列就改什麼,redis就是redis,rebbitmq就為rebbitmq
command=php /home/vagrant/code/dcat/artisan queue:work redis --sleep=3 --tries=3
autostart=true
autorestart=true
user=root
numprocs=8
redirect_stderr=true
stdout_logfile=/home/forge/app.com/worker.log
stopwaitsecs=3600

然後chmod -R 777 /home/forge/app.com/worker.log

還有一個地方,就是/etc/supervisord/下的supervisord.conf的一個配置項:
[include] files = /etc/supervisor/conf.d/*.conf
它的意思是指向conf.d下的配置檔案,上一篇文章的配置一樣,根據具體情況配置即可。
然後開啟:

sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start laravel-worker:*

如果執行到最後一步沒有報錯且沒有

laravel-worker:laravel-worker_00: started

的提示資訊,那就執行:

sudo supervisorctl status

檢視佇列是否開啟,如果顯示:

laravel-worker:laravel-worker_00   RUNNING   pid 3937, uptime 0:05:37
laravel-worker:laravel-worker_01   RUNNING   pid 3938, uptime 0:05:37
laravel-worker:laravel-worker_02   RUNNING   pid 3939, uptime 0:05:37
laravel-worker:laravel-worker_03   RUNNING   pid 3940, uptime 0:05:37
laravel-worker:laravel-worker_04   RUNNING   pid 3941, uptime 0:05:37
laravel-worker:laravel-worker_05   RUNNING   pid 3942, uptime 0:05:37
laravel-worker:laravel-worker_06   RUNNING   pid 3943, uptime 0:05:37
laravel-worker:laravel-worker_07   RUNNING   pid 3944, uptime 0:05:37

那麼恭喜你,你的佇列開啟成功。

使用

控制器:

use App\Jobs\FlowQueue;
$user = [
    'uid'=>1,
    'name'=>'李大',
    'phone'=>'1388888888',
    'score'=>[
        'chinese'=>(double)110,
        'math'=>(double)100,
        'english'=>(double)90,
    ],
    'type'=>2
];
FlowQueue::dispatch($user);

佇列:

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

    protected $accessLogs;

    /**
     * Create a new job instance.
     *
     * @param AccessLog $accessLogs
     */
    public function __construct($accessLogs)
    {
        //
        $this->accessLogs = $accessLogs;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //
        $logs = $this->accessLogs;
        AccessLog::create($logs);
    }
}

執行結果:

(請忽略mongodb時間差8小時問題,解決辦法就是在使用mongodb的模型加入這個:

use DateTimeInterface;
use Illuminate\Support\Carbon;
public function serializeDate(DateTimeInterface $date){
  return Carbon::instance($date)->toDateTimeString();
}

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章