Queues trong Laravel, dùng để xử lý các tác vụ mất nhiều thời gian
Trong bài viết này, chúng ta sẽ tìm hiểu cách sử dụng tính năng Queues của Laravel để đưa các tác vụ vào hàng đợi và xử lý các tác vụ mất nhiều thời gian.
Bài viết sẽ đi qua các bước cài đặt và cấu hình Queues trên Laravel, cách tạo các tác vụ để đưa vào hàng đợi, cách đưa các tác vụ vào hàng đợi và xử lý các tác vụ từ hàng đợi. Ngoài ra, bài viết cũng sẽ giới thiệu về các driver hàng đợi khác nhau và cách sử dụng chúng trên Laravel.
Queues trong laravel là gì ?
Queues (hàng đợi) là tính năng của Laravel, cho phép đưa các tác vụ vào hàng đợi để xử lý một cách bất đồng bộ, giúp ứng dụng có thể xử lý các tác vụ mất nhiều thời gian mà không làm chậm hoạt động của ứng dụng. Khi ta đưa các tác vụ vào hàng đợi, chúng sẽ được đưa vào một bộ đệm và xử lý một cách độc lập với ứng dụng chính. Điều này giúp cho ứng dụng vẫn hoạt động ổn định mà không bị tắc nghẽn do các tác vụ mất nhiều thời gian. Khi các tác vụ được xử lý xong, kết quả sẽ được ghi nhận và trả về cho ứng dụng.
Với tính năng Queues, Laravel cung cấp các driver khác nhau để đưa các tác vụ vào hàng đợi, bao gồm các driver được hỗ trợ sẵn như Redis, Beanstalkd, và Amazon SQS. Ta cũng có thể viết các driver tùy chỉnh để sử dụng các hệ thống hàng đợi khác.
Bài viết này được đăng tại [free tuts .net]
1. Khởi tạo Queues
Để sử dụng tính năng Queues trong Laravel, bạn cần phải khởi tạo hàng đợi trước. Hàng đợi có thể được cấu hình bằng nhiều driver khác nhau như Redis, Beanstalkd và Amazon SQS. Chúng ta sẽ tập trung vào việc sử dụng driver Redis để khởi tạo hàng đợi.
Cài đặt Redis
Trước khi khởi tạo hàng đợi bằng Redis, bạn cần phải cài đặt Redis trên máy tính của mình. Nếu bạn sử dụng hệ điều hành Ubuntu, bạn có thể cài đặt Redis bằng câu lệnh sau:
sudo apt-get install redis-server
Cấu hình Queue
Sau khi cài đặt Redis, bạn cần cấu hình Queue để sử dụng Redis driver. Bạn có thể cấu hình Queue trong file config/queue.php. Tìm đến phần connections và thêm một connection mới với driver là redis.
Ví dụ:
'connections' => [ 'redis' => [ 'driver' => 'redis', 'connection' => 'default', 'queue' => 'default', 'retry_after' => 90, 'block_for' => null, ], // ... ],
Trong đó:
- driver: là tên driver bạn sử dụng, ở đây là redis.
- connection: là tên của Redis connection bạn muốn sử dụng, nếu bạn không cấu hình gì thì mặc định là default.
- queue: là tên của queue bạn muốn sử dụng, nếu bạn không cấu hình gì thì mặc định là default.
- retry_after: là thời gian (đơn vị là giây) mà một job sẽ được thực thi lại nếu nó thất bại.
- block_for: là thời gian (đơn vị là giây) mà một worker sẽ đợi để lấy job mới nếu không có job nào trong queue. Nếu không cấu hình gì thì mặc định là null.
Khởi tạo Queue
Sau khi cấu hình Queue, bạn có thể khởi tạo Queue bằng câu lệnh sau:
php artisan queue:work redis --queue=queue_name
Trong đó:
- redis là tên driver bạn sử dụng.
- queue_name là tên của queue bạn muốn sử dụng, nếu bạn không cấu hình gì thì mặc định là default.
Nếu bạn muốn khởi tạo một worker để xử lý các job trong queue, bạn có thể sử dụng câu lệnh sau:
php artisan queue:work redis --queue
2. Tạo Job
Một job là một class đại diện cho một tác vụ được thực hiện trong background. Một job có thể được gửi đến hàng đợi (queue) để xử lý sau, điều này giúp cho ứng dụng của bạn không bị chặn lại khi thực hiện các tác vụ mất nhiều thời gian.
Để tạo một job trong Laravel, bạn có thể sử dụng artisan command make:job.
Ví dụ, để tạo một job có tên là ProcessPodcast, bạn có thể chạy lệnh sau:
php artisan make:job ProcessPodcast
Sau khi chạy lệnh này, Laravel sẽ tạo ra một file mới tên là ProcessPodcast.php trong thư mục app/Jobs. File này chứa một class đại diện cho job bạn vừa tạo.
Trong class này, bạn có thể thực hiện các tác vụ cần thiết để xử lý job. Hàm handle() sẽ được gọi khi job được xử lý trong hàng đợi. Ví dụ, để xử lý việc xử lý một podcast, bạn có thể thực hiện như sau:
namespace App\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; class ProcessPodcast implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected $podcast; /** * Create a new job instance. * * @param Podcast $podcast * @return void */ public function __construct($podcast) { $this->podcast = $podcast; } /** * Execute the job. *freetuts.net * @return void */ public function handle() { // Xử lý việc tải và xử lý podcast tại đây. } }
Ở đây, class ProcessPodcast implement interface ShouldQueue để cho Laravel biết rằng đây là một job và phải được đưa vào hàng đợi để xử lý.
Hàm __construct() là constructor của class, nó nhận vào các tham số cần thiết để thực hiện job. Trong ví dụ này, chúng ta truyền vào một đối tượng Podcast.
Hàm handle() chứa các tác vụ cần thiết để xử lý job. Trong ví dụ này, chúng ta sẽ xử lý việc tải và xử lý podcast.
Sau khi bạn đã tạo một job, bạn có thể đưa nó vào hàng đợi bằng cách sử dụng facade Bus. Ví dụ, để đưa job ProcessPodcast vào hàng đợi, bạn có thể sử dụng câu lệnh sau:
use App\Jobs\ProcessPodcast; use Illuminate\Support\Facades
3. Đưa các tác vụ vào Queues (hàng đợi)
Để đưa các tác vụ vào hàng đợi trong Laravel, ta có thể sử dụng một trong những cách sau:
Sử dụng Dispatch Method
Phương thức dispatch() là một trong những phương thức cơ bản nhất để đưa một job vào hàng đợi trong Laravel. Để sử dụng phương thức này, bạn cần import namespace của job và sau đó gọi phương thức dispatch() để đưa job vào hàng đợi.
Ví dụ:
use App\Jobs\SendEmailJob; dispatch(new SendEmailJob($user));
Trong đó, SendEmailJob là tên của class job, và $user là đối tượng user được truyền vào constructor của job.
Sử dụng Job chaining
Job chaining cho phép bạn sử dụng một chuỗi các jobs liên tiếp nhau để thực hiện một tác vụ phức tạp hơn. Ví dụ, nếu bạn muốn thực hiện một tác vụ gửi email cho người dùng mới đăng ký, sau đó lưu thông tin của người dùng vào cơ sở dữ liệu, bạn có thể sử dụng job chaining để thực hiện hai tác vụ này một cách liên tục nhau.
Ví dụ:
use App\Jobs\SendWelcomeEmail; use App\Jobs\SaveUserToDatabase; freetuts.net SendWelcomeEmail::withChain([ new SaveUserToDatabase($user) ])->dispatch($user);
Trong đó, SendWelcomeEmail và SaveUserToDatabase là hai class job, và $user là đối tượng user được truyền vào cho cả hai job.
Sử dụng Delayed Dispatching
Delayed dispatching cho phép bạn đưa một job vào hàng đợi nhưng không thực hiện ngay lập tức, mà sẽ chờ đợi một khoảng thời gian xác định trước khi thực hiện. Để sử dụng delayed dispatching, bạn có thể sử dụng phương thức delay() kết hợp với phương thức dispatch().
Ví dụ:
use App\Jobs\SendReminderEmail; SendReminderEmail::dispatch($user)->delay(now()->addMinutes(10));
Trong đó, SendReminderEmail là tên của class job, $user là đối tượng user được truyền vào constructor của job, và now()->addMinutes(10) là thời điểm delay job, ở đây là 10 phút sau khi job được đưa vào hàng đợi.
Như vậy, đó là ba cách chính để đưa các tác vụ vào hàng đợi trong Laravel. Bạn có thể chọn phương pháp phù hợp với nhu cầu và yêu cầu của ứng dụng của mình.
4.Xử lý tác vụ trong Queue
Tạo một job trong Laravel bằng command
Ví dụ, để tạo một job tên là SendEmail, bạn có thể chạy command sau:
php artisan make:job SendEmail
Sau đó, Laravel sẽ tạo một file mới trong thư mục app/Jobs với tên SendEmail.php.
Trong file SendEmail.php, bạn có thể định nghĩa các tác vụ cần được thực hiện trong job.
Ví dụ:
public function handle() { // code để gửi email }
Sau khi định nghĩa job, bạn có thể đưa nó vào hàng đợi để được xử lý. Để đưa job vào hàng đợi, bạn có thể sử dụng command dispatch như sau:
use App\Jobs\SendEmail; SendEmail::dispatch();
Trong đó, SendEmail là tên của job đã được định nghĩa ở bước trước.
Nếu bạn muốn đặt các tùy chọn khác cho job, bạn có thể truyền chúng vào phương thức dispatch như sau:
SendEmail::dispatch()->delay(now()->addMinutes(10))->onQueue('emails');
Trong đó, delay là để đặt thời gian trễ để thực hiện job, onQueue để đặt tên cho queue mà job sẽ được đưa vào.
Để xử lý các job trong hàng đợi,bạn cần chạy command trên terminal. Sau đó, Laravel sẽ bắt đầu xử lý các job trong queue. Nếu có job mới được đưa vào queue, Laravel sẽ tiếp tục xử lý chúng cho đến khi queue trống hoặc command được tắt.
php artisan queue:work
Nếu bạn muốn chạy nhiều worker cùng lúc để xử lý các job trong queue, bạn có thể sử dụng command để chạy nhiều worker với các tùy chọn khác nhau. :
php artisan queue:work --queue=<tên_queue> --tries=<số_lần_thử> --timeout=<thời_gian_timeout>
5. Sử dụng Queue trong Controller
Để sử dụng queue trong controller trong Laravel, bạn có thể sử dụng hàm dispatch() để đưa một job vào hàng đợi. Bạn có thể gọi hàm này từ trong method của controller để thực hiện các tác vụ mất nhiều thời gian mà không làm ảnh hưởng đến việc xử lý request hiện tại.
Ví dụ, nếu bạn muốn thực hiện một tác vụ gửi email cho người dùng sau khi họ đăng ký, bạn có thể tạo một class job SendEmailJob để xử lý tác vụ gửi email này. Sau đó, bạn có thể sử dụng hàm dispatch() để đưa job này vào hàng đợi trong controller.
Ví dụ:
use App\Jobs\SendEmailJob; class UserController extends Controller { public function register(Request $request) { // validate the request // create the user // freetuts.net // dispatch the SendEmailJob SendEmailJob::dispatch($user); // return the response } }
Trong đó, SendEmailJob là tên của class job, $user là đối tượng user được truyền vào constructor của job. Sau khi job được đưa vào hàng đợi bằng cách sử dụng dispatch(), controller sẽ tiếp tục xử lý các tác vụ khác và trả về kết quả cho request hiện tại.
Điều này giúp tăng hiệu suất và giảm thời gian phản hồi của ứng dụng khi phải xử lý các tác vụ mất nhiều thời gian.
6. Xác định số lượng Worker
Số lượng worker trong Laravel là số lượng các tiến trình (process) đang chạy để xử lý các job trong hàng đợi. Để xác định số lượng worker trong Laravel, bạn có thể thực hiện các bước sau:
1. Mở file .env trong project Laravel của bạn
2. Tìm đến dòng QUEUE_WORKER_NUM hoặc tạo mới nếu không có.
3. Thiết lập giá trị cho biến QUEUE_WORKER_NUM là số lượng worker mong muốn.
Ví dụ: QUEUE_WORKER_NUM=3.
Lưu ý rằng số lượng worker phù hợp sẽ phụ thuộc vào cấu hình server và yêu cầu xử lý của ứng dụng của bạn. Nếu số lượng worker quá ít, các job trong hàng đợi sẽ được xử lý chậm hơn, còn nếu quá nhiều, ứng dụng của bạn sẽ tốn nhiều tài nguyên hệ thống và không hiệu quả.
Sau khi xác định số lượng worker, bạn có thể sử dụng command php artisan queue:work để bắt đầu các tiến trình worker trong Laravel. Ví dụ, để bắt đầu 3 tiến trình worker, bạn có thể chạy command:
php artisan queue:work --queue=default --tries=3 --daemon --timeout=60 --sleep=3 --max-time=3600 --max-jobs=0 --stop-when-empty --processes=3
Trong đó, --processes=3 là tham số để xác định số lượng worker là 3.
7. Sử dụng Supervisor để quản lý Worker
Supervisor là một công cụ quản lý tiến trình trên Linux và macOS, cho phép bạn dễ dàng khởi động, tạm dừng và khôi phục các tiến trình. Bằng cách sử dụng Supervisor, bạn có thể đảm bảo rằng các tiến trình worker trong Laravel luôn được chạy và sẵn sàng xử lý các job trong hàng đợi.
Để sử dụng Supervisor để quản lý worker trong Laravel, bạn có thể thực hiện các bước sau:
Cài đặt Supervisor bằng cách chạy command sau trên terminal
sudo apt-get install supervisor
Tạo một file cấu hình cho tiến trình worker trong Supervisor bằng cách tạo một file mới trong thư mục /etc/supervisor/conf.d/. Ví dụ, tạo file laravel-worker.conf.
Mở file 'laravel-worker.conf ' và thêm các cấu hình sau :
[program:laravel-worker] process_name=%(program_name)s_%(process_num)02d command=php /path/to/your/laravel/project/artisan queue:work --queue=default --tries=3 --timeout=60 autostart=true autorestart=true user=www-data numprocs=3 redirect_stderr=true stdout_logfile=/path/to/your/laravel/project/storage/logs/worker.log
Trong đó, numprocs=3 là tham số để xác định số lượng worker là 3. command là lệnh để chạy worker và stdout_logfile là đường dẫn để lưu log của worker.
Lưu và đóng file cấu hình, sau đó chạy command sau để đảm bảo rằng Supervisor đã load được file cấu hình mới
sudo supervisorctl reread sudo supervisorctl update
Khởi động worker bằng cách chạy command sau
sudo supervisorctl start laravel-worker:*
Để kiểm tra trạng thái của worker, bạn có thể sử dụng command
sudo supervisorctl status
Nếu tất cả các worker đang chạy bình thường, bạn sẽ thấy kết quả hiển thị tên worker và trạng thái RUNNING. Nếu có lỗi xảy ra, bạn có thể kiểm tra log của worker để tìm hiểu thêm thông tin về lỗi đó.
Kết bài viết
Trong bài viết này, chúng ta đã tìm hiểu về Queues trong Laravel và cách sử dụng chúng để xử lý các tác vụ mất nhiều thời gian trong ứng dụng của mình.
Chúng ta đã bắt đầu với khái niệm Queues và cách chúng hoạt động trong Laravel. Sau đó, chúng ta đã học cách khởi tạo và tạo job trong Laravel, đưa các tác vụ vào hàng đợi và sử dụng Queue trong Controller. Chúng ta cũng đã xác định cách thiết lập số lượng worker trong Laravel và sử dụng Supervisor để quản lý chúng.
Cuối cùng, chúng ta đã xem xét cách xử lý các tác vụ trong hàng đợi bằng cách sử dụng các worker để thực thi chúng. Như vậy, sử dụng Queues trong Laravel là một cách tốt để tăng hiệu suất và giảm thời gian phản hồi trong ứng dụng của bạn.
Hy vọng bài viết này sẽ giúp bạn hiểu rõ hơn về cách sử dụng Queues trong Laravel để xử lý các tác vụ mất nhiều thời gian.
Một số câu hỏi liên quan về Queues
1. Queues trong Laravel là gì?
Queues trong Laravel là một tính năng cho phép xử lý các tác vụ mất nhiều thời gian bằng cách đưa chúng vào một hàng đợi và thực thi chúng bởi các worker. Điều này giúp cho ứng dụng có thể hoạt động một cách hiệu quả và không bị gián đoạn bởi các tác vụ lâu dài.
2. Làm thế nào để sử dụng Queues trong Laravel để xử lý các tác vụ mất nhiều thời gian?
Để sử dụng Queues trong Laravel, bạn cần bắt đầu bằng việc khởi tạo và cấu hình một hàng đợi. Sau đó, bạn có thể tạo job để đưa các tác vụ vào hàng đợi. Để xử lý các tác vụ trong hàng đợi, bạn cần sử dụng các worker để thực thi chúng. Laravel cung cấp nhiều driver khác nhau để hỗ trợ việc xử lý hàng đợi, bao gồm Redis, Beanstalkd, và Amazon SQS.
3. Làm thế nào để quản lý số lượng worker và quá trình xử lý Queues trong Laravel?
Bạn có thể quản lý số lượng worker bằng cách thiết lập số lượng worker cần thiết để xử lý các tác vụ trong hàng đợi. Nếu bạn đang sử dụng driver Redis hoặc Beanstalkd, bạn có thể sử dụng Supervisor để quản lý các worker và quá trình xử lý Queues. Supervisor cho phép bạn quản lý các worker bằng cách giám sát và khởi động lại chúng khi cần thiết, giúp đảm bảo rằng các tác vụ trong hàng đợi được xử lý một cách hiệu quả.