Laravel Queue và sử dụng supervisor để xử lý nhiều hàng đợi

Chắc hẳn những anh em mới bắt đầu tiếp cận và làm việc với Laravel đều thấy việc gửi 1 email thật đơn giản khi sử cần sử dụng hàm Mail của Laravel đúng không ạ. Mình cũng thế. Khi mới học và làm 1 cài con web cỏ (thực ra là mấy bài tập nho nhỏ của các thầy giao cho 😀 ) nghĩ thật đơn giản, ấn nút gửi là xong. Nhưng khi được thầy hỏi, nếu gửi 1 lúc cho 10 nghìn người hay 10 nghìn người cùng thao tác nút gửi mail đó sẽ ra sao. Chắc server của mình cứ thế load mãi, load mãi và lăn đùng ra mà die mất 😄.

Và từ đó mình đã tìm hiểu Laravel Queue và Supervisor.

Laravel Queue là gì?

Queue là một danh sách những công việc cần làm (job) hàng đợi cần được xử lý theo thứ tự. Ví dụ khi có 1000 người click vào nút gửi mail của mình, tất cả sẽ được xếp theo thứ tự và việc gửi mail sẽ được xử lý lần lượt. Và các job sẽ có thể được lưu vào nhiều nơi khác nhau (database, redis), tùy theo việc bạn cài đặt trong env. Ví dụ, nếu bạn muốn lưu job vào database:

QUEUE_DRIVER=database

và nhớ đừng quên chạy

php artisan queue:table
php artisan migrate

Tạo job

Đầu tiên bạn cần tạo cho mình 1 job để xử lý công việc của bạn. Ví dụ ở đây mình cần gửi mail reset mật khẩu

php artisan make:job SendEmailResetPassword

Và trong app/Jobs của mình sẽ có file SendEmailResetPassword.php như sau:

<?php

namespace App\Jobs;

use App\Mail\ResetPasswordMail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;

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

    /**
     * Create a new job instance.
     *
     * @return void
     */
    private $dataReset;

    public function __construct($dataReset)
    {
        $this->dataReset = $dataReset;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        Mail::to($this->dataReset['email'])->send(new ResetPasswordMail($this->dataReset));
    }
}

Tạo template email

Các bạn hãy chạy lệnh sau

php artisan make:mail ResetPasswordMail

Và giờ hãy vào app/Mail và bạn sẽ thấy file vừa tạo. Hiểu cơ bản thì đây sẽ là file giúp bạn bind data vào trong mail và gửi cho người dùng

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class ResetPasswordMail extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    private $dataReset;

    public function __construct($dataReset)
    {
        $this->dataReset = $dataReset;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->with($this->dataReset)->view('mail.reset-password');
    }
}

Tiếp tợi hãy tạo một file blade nhé. Như ở trên thì mình sẽ tạo file reset-password.blade.php trong views/mail

Dispatch Job

Và giờ, ở trong Controller bạn hãy disptach job của mình nhé

SendEmailResetPassword::dispatch($dataReset);

Chạy các jobs trong queue

Để chạy các jobs thì các bạn hãy dùng lệnh:

php artisan queue:work --tries=3

--tries=3 sẽ là số lần bạn thực hiện lại job đó nếu bị fail. Còn một vài thông số nữa về thời gian chờ, thời gian nghỉ,.. thì các bạn chịu khó lên docs của Laravel và đọc nhé, ở đây mình sẽ chỉ giới thiệu qua như vậy 

Cách chạy queue trên server

Ơ nhưng mà chẳng lẽ lúc nào chúng ta cũng phải chạy queue:work ở trên server ư. Tất nhiên là không rồi, bạn có thể xử dụng supervisor để giám sát xử lý các queue trên server

Supervisor

Supervisor là một hệ thống client/server được sử dụng để kiểm soát một số những tiến trình cụ thể của hệ điều hành UNIX, cụ thể hơn là các quy trình liên quan tới một dự án hoặc một khách hàng. Ví dụ, bạn có thể sử dụng supervisor để quản lý hàng đợi trong ứng dụng Laravel của bạn

Các thành phần của supervisor bao gồm:

  • supervisor: phần máy chủ của hệ thống
  • supervisorctl: giao diện dòng lệnh để tương tác với server
  • Web server: Một giao diện web đơn giản để trực quan hóa một số chức năng cơ bản của supervisorctl
  • XML-RPC Interface: Giống với HTTP server sử dụng bởi web client, XML-RPC Interface có thể được sử dụng để điều khiển các chương trình của supervisor

Để cài đặt bàn hãy dùng câu lệnh

sudo apt-get install supervisor

Check status:

sudo systemctl status supervisor.service

Tương tự để khởi động, tắt, tạm dừng chúng ta lần lượt thay  status bằng  enablestartstopdisable

Các file cấu hình sẽ nằm trong thư mục etc/supervisor/conf.d. Ở đây bạn hãy tạo file reset-password.conf và cấu hình như sau nhé

[program:reset-password]
process_name=%(program_name)s_%(process_num)02d
command=php duong-dan-toi-folder-project/artisan queue:work --tries=3
autostart=true
autorestart=true
user=forge
numprocs=8
redirect_stderr=true
stdout_logfile=/duong-dan-ban-muon-luu-log/reset-mail.log

Trong đó:

  • autostart: thông báo là chương trình sẽ tự động được khởi động khi supervisor được khởi động
  • autorestart: nếu chương trình bị tắt vì bất cứ lý do gì, lệnh này sẽ thông báo cho supervisor khởi động lại chương trình
  • stderr_logfilestdout_logfile: định nghĩa đường dẫn log đầu ra và log lỗi
  • redirect_stderr: nếu là true thì stderr sẽ bị redirect để xuất vào file chỉ định ở stdout_logfile
  • numprocs: số lượng tiến trình mà Supervisor sẽ chạy. Ví dụ để gửi mail, ta để numprocs=4, nghĩa là 4 tiến trình cùng chạy task gửi mail.
  • Xem thêm các section value khác tại đây: http://supervisord.org/configuration.html#program-x-section-values

Sau đó lưu lại và chạy các lệnh sau nhé:

$supervisorctl reread
$supervisorctl update
$supervisorctl start reset-password:*

Tìm hiểu thêm chạy supervisor trên docker:  https://docs.docker.com/config/containers/multi-service_container/

Tham khảo:  https://www.vultr.com/https://www.digitalocean.com/https://youtube.com/https://viblo.asia/

Cảm ơn tất cả mọi người đã đọc.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *