NTM Solutions

Thứ Năm, 24 tháng 9, 2026

🚀LARAVEL 13 — BÀI 48 — QUEUE WORKER & SCHEDULER

Bài 47, chúng ta đã cấu hình:

Internet
    ↓
Nginx
    ↓
PHP-FPM
    ↓
Laravel 13

Nhưng một ứng dụng thực tế thường không chỉ xử lý request ngay lập tức.

Ví dụ Blog CMS của chúng ta có thể cần:

  • gửi email;

  • gửi notification;

  • xử lý ảnh;

  • tạo báo cáo;

  • xóa dữ liệu cũ;

  • đồng bộ dữ liệu;

  • gửi email hàng loạt;

  • chạy tác vụ mỗi ngày;

  • dọn database;

  • kiểm tra bài viết scheduled.

Nếu bắt người dùng chờ tất cả những việc này hoàn thành trong HTTP request thì website sẽ chậm.

Laravel cung cấp hai cơ chế rất quan trọng:

Queue
Scheduler

Trong bài này chúng ta sẽ đưa cả hai lên VPS production.


1. Queue là gì?

Queue có thể hiểu đơn giản là:

Đưa một công việc vào hàng đợi để xử lý sau.

Ví dụ người dùng đăng ký tài khoản:

User Register
     │
     ▼
Laravel
     │
     ├── Lưu User
     │
     └── Đưa Email vào Queue
                │
                ▼
             Worker
                │
                ▼
            Gửi Email

Thay vì:

User
 │
 ▼
Register
 │
 ▼
Gửi Email
 │
 ▼
Chờ SMTP
 │
 ▼
Response

chúng ta có:

User
 │
 ▼
Register
 │
 ▼
Queue Job
 │
 ▼
Response nhanh

Sau đó Worker xử lý email ở background.


2. Queue giải quyết vấn đề gì?

Giả sử Blog CMS có chức năng gửi email cho 10.000 người dùng.

Nếu xử lý trực tiếp:

foreach ($users as $user) {
    Mail::to($user)->send(...);
}

request có thể phải chờ rất lâu.

Không nên bắt browser chờ:

Browser
   │
   │ Request
   ▼
Laravel
   │
   ├── Email 1
   ├── Email 2
   ├── Email 3
   ├── ...
   └── Email 10000
        │
        ▼
     Response

Thay vào đó:

Browser
   │
   ▼
Laravel
   │
   ▼
Queue
   │
   └── 10000 jobs
            │
            ▼
         Worker

Browser nhận response sớm hơn.


3. Queue Job là gì?

Một Job đại diện cho một công việc.

Ví dụ:

SendWelcomeEmail

hoặc:

ProcessPostImage

hoặc:

GenerateReport

Tạo Job:

php artisan make:job SendWelcomeEmail

Laravel tạo:

app/Jobs/SendWelcomeEmail.php

4. Cấu trúc một Job

Ví dụ:

<?php

namespace App\Jobs;

use App\Models\User;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;

class SendWelcomeEmail implements ShouldQueue
{
    use Queueable;

    public function __construct(
        public User $user
    ) {
    }

    public function handle(): void
    {
        // Xử lý công việc
    }
}

Điểm quan trọng:

implements ShouldQueue

cho Laravel biết Job này cần được xử lý thông qua Queue.


5. Dispatch Job

Sau khi tạo Job:

SendWelcomeEmail::dispatch($user);

Ví dụ:

use App\Jobs\SendWelcomeEmail;

SendWelcomeEmail::dispatch($user);

Lúc này ứng dụng không nhất thiết phải thực hiện toàn bộ công việc ngay trong request.

Job được đưa vào Queue để Worker xử lý.


6. Queue Driver

Laravel hỗ trợ nhiều queue backend.

Một số lựa chọn phổ biến:

Database
Redis
Amazon SQS

Trong khóa học, chúng ta bắt đầu bằng:

Database Queue

vì dễ hiểu và phù hợp để học.


7. Database Queue

Database Queue lưu Job vào database.

Mô hình:

Laravel
   │
   ▼
jobs table
   │
   ▼
Queue Worker
   │
   ▼
handle()

Laravel có thể tạo migration cho jobs table bằng:

php artisan make:queue-table

Sau đó:

php artisan migrate

Database sẽ có bảng:

jobs

Ngoài ra có thể có:

failed_jobs

để lưu những Job thất bại.


8. Cấu hình Queue

Trong .env:

QUEUE_CONNECTION=database

Sau khi thay đổi .env, trong production nên đảm bảo configuration cache được cập nhật.

Ví dụ:

php artisan config:clear

hoặc sau khi deploy:

php artisan optimize

9. Chạy Queue Worker

Đây là phần cực kỳ quan trọng.

Queue chỉ chứa Job.

Ai xử lý Job?

Queue Worker

Chạy:

php artisan queue:work

Worker sẽ:

Queue
 │
 ├── Job 1
 ├── Job 2
 ├── Job 3
 └── Job 4
      │
      ▼
    Worker
      │
      ▼
   handle()

10. queue:work chạy liên tục

Khi chạy:

php artisan queue:work

Laravel Worker không chỉ xử lý một Job rồi kết thúc.

Nó tiếp tục chờ:

Job
 ↓
Process
 ↓
Job
 ↓
Process
 ↓
Job
 ↓
Process
 ↓
...

Đây là một long-running process.

Vì vậy production cần một process manager để đảm bảo Worker luôn được chạy.


11. Không nên chạy Worker bằng SSH thủ công

Ví dụ:

php artisan queue:work

Bạn SSH vào VPS và chạy.

Sau đó:

SSH disconnect

Worker có thể kết thúc.

Đây không phải cách triển khai production tốt.

Chúng ta cần:

Supervisor

hoặc một process manager tương đương.


12. Supervisor là gì?

Supervisor là process manager.

Nó có nhiệm vụ:

Kiểm tra Worker
      │
      ├── Worker đang chạy
      │       ↓
      │     OK
      │
      └── Worker chết
              ↓
           Restart

Như vậy:

Laravel Queue
      ↓
queue:work
      ↓
Supervisor
      ↓
Luôn duy trì Worker

13. Cài Supervisor trên Ubuntu

Trên VPS:

sudo apt update

Sau đó:

sudo apt install supervisor

Kiểm tra:

sudo systemctl status supervisor

14. Tạo Supervisor configuration

Giả sử project:

/var/www/blog

Tạo:

sudo nano /etc/supervisor/conf.d/blog-worker.conf

Nội dung:

[program:blog-worker]

process_name=%(program_name)s_%(process_num)02d

command=php /var/www/blog/artisan queue:work database --sleep=3 --tries=3 --timeout=90

autostart=true
autorestart=true

stopasgroup=true
killasgroup=true

user=www-data

numprocs=2

redirect_stderr=true

stdout_logfile=/var/www/blog/storage/logs/worker.log

stopwaitsecs=3600

Cấu hình này tạo:

Worker 1
Worker 2

15. Giải thích numprocs

numprocs=2

nghĩa là chạy hai Worker.

Supervisor
   │
   ├── Worker 1
   │
   └── Worker 2

Nếu có nhiều Job:

Job 1 ── Worker 1
Job 2 ── Worker 2
Job 3 ── Worker 1
Job 4 ── Worker 2

Nhờ đó có thể xử lý nhiều công việc đồng thời.

Không nên tăng numprocs tùy tiện.

VPS ít CPU/RAM mà chạy quá nhiều Worker có thể làm server quá tải.


16. --sleep

--sleep=3

Worker sẽ chờ 3 giây trước khi kiểm tra Queue lại khi không có Job.

Ví dụ:

Không có Job
   ↓
Chờ 3 giây
   ↓
Kiểm tra
   ↓
Không có
   ↓
Chờ 3 giây

17. --tries

--tries=3

Nếu Job thất bại:

Attempt 1
   ↓
Fail
   ↓
Attempt 2
   ↓
Fail
   ↓
Attempt 3
   ↓
Fail
   ↓
Failed Job

Không phải mọi Job đều nên retry vô hạn.


18. --timeout

--timeout=90

Worker cho phép Job chạy tối đa khoảng thời gian cấu hình trước khi bị timeout.

Con số thực tế cần được chọn dựa trên loại Job.

Ví dụ:

Gửi email

có thể cần thời gian khác:

Xử lý video

hoặc:

Generate report

Không nên đặt timeout quá thấp đối với Job cần nhiều thời gian.


19. Khởi động Supervisor

Sau khi tạo configuration:

sudo supervisorctl reread

Sau đó:

sudo supervisorctl update

Kiểm tra:

sudo supervisorctl status

Ví dụ:

blog-worker:blog-worker_00    RUNNING
blog-worker:blog-worker_01    RUNNING

20. Restart Worker

Khi deploy code mới, có một vấn đề quan trọng.

Queue Worker là process chạy lâu dài.

Nó có thể tiếp tục sử dụng code cũ đã được load vào memory.

Laravel cung cấp:

php artisan queue:restart

để yêu cầu Worker restart một cách graceful sau khi hoàn thành Job hiện tại. Laravel documentation cũng lưu ý rằng queue workers là long-lived processes và cần được restart/reload sau deployment.

Với Laravel 13, có thêm command tổng quát:

php artisan reload

để terminate các reloadable long-running services sau deployment; process monitor như Supervisor có thể khởi động chúng lại.

Trong mô hình VPS + Supervisor của khóa học, có thể dùng:

php artisan queue:restart

sau deployment.


21. Queue Failed Jobs

Một Job có thể thất bại.

Ví dụ:

SMTP Server
    ↓
Connection failed

hoặc:

API
    ↓
Timeout

Laravel có thể lưu Job thất bại trong:

failed_jobs

Xem:

php artisan queue:failed

22. Retry Failed Job

Có thể retry:

php artisan queue:retry all

hoặc một Job cụ thể:

php artisan queue:retry 5

Trong đó:

5

là ID của failed Job.


23. Xóa Failed Jobs

Có thể xóa một Job:

php artisan queue:forget 5

Hoặc xóa toàn bộ failed jobs:

php artisan queue:flush

Cẩn thận với:

queue:flush

vì nó xóa danh sách failed jobs.


24. Ví dụ Queue trong Blog CMS

Blog CMS có thể có:

Post Published
      │
      ▼
SendPostPublishedNotification
      │
      ▼
Queue
      │
      ▼
Worker
      │
      ├── Email
      └── Notification

Controller không cần xử lý tất cả công việc nặng trong request.


25. Queue Email

Laravel Mail có thể được queue.

Ví dụ Mailable:

<?php

namespace App\Mail;

use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;

class WelcomeMail extends Mailable implements ShouldQueue
{
    public function build()
    {
        return $this->subject('Welcome')
            ->view('emails.welcome');
    }
}

Khi Mailable implement:

ShouldQueue

email sẽ được đưa vào Queue thay vì bắt request phải chờ việc gửi email hoàn thành. Laravel 13 documentation hỗ trợ queued mailables thông qua ShouldQueue.


26. Queue Listener

Bài 34 — Event & Listener, chúng ta đã học Event và Listener.

Listener cũng có thể chạy Queue.

Ví dụ:

use Illuminate\Contracts\Queue\ShouldQueue;

class SendPostNotification implements ShouldQueue
{
    public function handle(PostPublished $event): void
    {
        // Send notification
    }
}

Mô hình:

Event
 │
 ▼
Listener
 │
 ├── ShouldQueue
 │
 ▼
Queue
 │
 ▼
Worker

Laravel 13 hỗ trợ queued listeners và các cơ chế retry/backoff cho listener.


27. Queue Routing trong Laravel 13

Laravel 13 có thêm khả năng queue routing theo Job class.

Ví dụ:

use Illuminate\Support\Facades\Queue;

Queue::route(
    ProcessPodcast::class,
    connection: 'redis',
    queue: 'podcasts'
);

Điều này cho phép định tuyến mặc định cho một Job cụ thể thay vì phải cấu hình riêng ở từng nơi. Đây là một trong những thay đổi mới của Laravel 13.

Đối với khóa học cơ bản, chúng ta chưa cần sử dụng tính năng này ngay.

Điều quan trọng trước tiên là hiểu:

Job
 ↓
Queue
 ↓
Worker

28. Scheduler là gì?

Queue xử lý:

Công việc đang chờ

Scheduler xử lý:

Công việc cần chạy theo thời gian

Ví dụ:

Mỗi phút
Mỗi 5 phút
Mỗi giờ
Mỗi ngày
Mỗi tuần

Ví dụ Blog CMS:

00:00 mỗi ngày
    ↓
Dọn dữ liệu cũ

hoặc:

Mỗi 5 phút
    ↓
Kiểm tra bài viết scheduled

29. Scheduler khác Queue như thế nào?

Queue

Có Job
   ↓
Xử lý Job

Scheduler

Đến thời gian
   ↓
Chạy Task

Có thể kết hợp:

Scheduler
   │
   ▼
Dispatch Job
   │
   ▼
Queue
   │
   ▼
Worker

Đây là mô hình rất mạnh.


30. Định nghĩa Schedule

Trong Laravel hiện đại, scheduler có thể được định nghĩa trong:

routes/console.php

Ví dụ:

use Illuminate\Support\Facades\Schedule;

Schedule::call(function () {
    // Task
})->daily();

Laravel scheduler cho phép định nghĩa lịch chạy ngay trong source code thay vì phải tạo từng cron entry riêng cho từng task.


31. Schedule Artisan Command

Giả sử chúng ta có command:

php artisan make:command CleanOldPosts

Sau đó có thể schedule:

use Illuminate\Support\Facades\Schedule;

Schedule::command('posts:clean')
    ->daily();

Mỗi ngày Laravel sẽ chạy:

posts:clean

32. Schedule Job

Có thể schedule Job:

use App\Jobs\GenerateDailyReport;
use Illuminate\Support\Facades\Schedule;

Schedule::job(new GenerateDailyReport)
    ->daily();

Mô hình:

Scheduler
    │
    │ mỗi ngày
    ▼
GenerateDailyReport
    │
    ▼
Queue
    │
    ▼
Worker

Đây là cách kết hợp Scheduler và Queue rất phổ biến.


33. Các tần suất thường dùng

Ví dụ:

Schedule::command('posts:clean')
    ->daily();

Mỗi giờ:

Schedule::command('posts:sync')
    ->hourly();

Mỗi 5 phút:

Schedule::command('posts:sync')
    ->everyFiveMinutes();

Mỗi 10 phút:

Schedule::command('posts:sync')
    ->everyTenMinutes();

Mỗi ngày lúc 02:00:

Schedule::command('posts:clean')
    ->dailyAt('02:00');

34. Scheduler cần Cron

Đây là điểm rất quan trọng.

Laravel Scheduler không tự nhiên chạy chỉ vì chúng ta viết:

Schedule::command(...);

Trên production, server cần kích hoạt scheduler.

Một cách phổ biến là Cron chạy:

php artisan schedule:run

mỗi phút.

Cron:

Every minute
     │
     ▼
schedule:run
     │
     ▼
Laravel kiểm tra Schedule
     │
     ├── Task đến giờ?
     │       │
     │       └── Có → chạy
     │
     └── Chưa đến giờ → bỏ qua

Laravel documentation mô tả mô hình này: chỉ cần một cron entry chạy schedule:run mỗi phút; Laravel tự kiểm tra các task đã được định nghĩa.


35. Tạo Cron cho Laravel

Trên VPS:

crontab -e

Thêm:

* * * * * cd /var/www/blog && php artisan schedule:run >> /dev/null 2>&1

Ý nghĩa:

* * * * *

= mỗi phút.

Sau đó:

cd /var/www/blog

đi vào Laravel project.

Rồi:

php artisan schedule:run

36. Scheduler hoạt động thế nào?

Giả sử có:

Schedule::command('posts:clean')
    ->dailyAt('02:00');

Cron vẫn chạy:

01:58 → schedule:run
01:59 → schedule:run
02:00 → schedule:run
02:01 → schedule:run

Nhưng chỉ tại:

02:00

Laravel thực hiện:

posts:clean

Các phút còn lại:

Không có task cần chạy

37. Test Scheduler local

Trong môi trường development có thể chạy:

php artisan schedule:work

Scheduler sẽ chạy foreground và liên tục kiểm tra schedule. Đây là cách thuận tiện để test scheduler local thay vì cấu hình Cron trên máy development.


38. Ví dụ Scheduler cho Blog CMS

Blog CMS của chúng ta có thể có:

Scheduler
│
├── Every minute
│     └── Publish scheduled posts
│
├── Every hour
│     └── Update statistics
│
├── Daily
│     └── Cleanup old data
│
└── Weekly
      └── Generate report

Ví dụ:

use Illuminate\Support\Facades\Schedule;

Schedule::command('posts:publish-scheduled')
    ->everyMinute();

Schedule::command('stats:update')
    ->hourly();

Schedule::command('cleanup:old-data')
    ->dailyAt('02:00');

39. Prevent Overlapping

Một task có thể mất nhiều thời gian.

Ví dụ:

Task bắt đầu
   │
   ├── chạy 10 phút
   │
   └── Task tiếp theo lại được gọi

Có thể dẫn tới:

Task #1 đang chạy
Task #2 chạy cùng lúc

Nếu không muốn điều này, có thể dùng:

Schedule::command('reports:generate')
    ->daily()
    ->withoutOverlapping();

Khi đó Laravel cố gắng tránh việc task mới bắt đầu trong khi instance trước vẫn đang chạy.


40. Chạy trên một server

Nếu hệ thống có nhiều server:

Server 1
Server 2
Server 3

Scheduler có thể cần tránh việc cùng một task chạy trên cả ba server.

Trong các trường hợp phù hợp, Laravel cung cấp cơ chế:

->onOneServer()

Ví dụ:

Schedule::command('reports:generate')
    ->daily()
    ->onOneServer();

Cơ chế này cần cache backend phù hợp để các server phối hợp với nhau.


41. Scheduler + Queue

Đây là kiến trúc rất đáng nhớ:

                 Scheduler
                     │
                     │ mỗi ngày
                     ▼
              GenerateReport
                     │
                     ▼
                   Queue
                     │
                     ▼
                  Worker
                     │
                     ▼
              Report generated

Scheduler quyết định:

Khi nào?

Queue quyết định:

Xử lý công việc ở background như thế nào?


42. Queue + Scheduler trong Blog CMS

Một ví dụ thực tế:

                    BLOG CMS
                       │
          ┌────────────┴────────────┐
          │                         │
       Queue                    Scheduler
          │                         │
          ▼                         ▼
      Send Mail             Scheduled Posts
      Notification          Daily Cleanup
      Process Image         Daily Report
          │                         │
          ▼                         ▼
       Worker                  Artisan/Job

Đây chính là kiến trúc production mà chúng ta đang xây dựng.


43. Queue Worker và Deployment

Khi deploy version mới:

git pull

Sau đó:

composer install --no-dev --optimize-autoloader

Nếu có frontend:

npm install
npm run build

Migration:

php artisan migrate --force

Cache:

php artisan optimize

Sau đó cần xử lý Worker.

Có thể:

php artisan queue:restart

hoặc sử dụng:

php artisan reload

để reload các long-running services mà Laravel quản lý, tùy kiến trúc deployment.

Với VPS sử dụng Supervisor:

Deploy
  ↓
queue:restart
  ↓
Worker graceful exit
  ↓
Supervisor phát hiện process kết thúc
  ↓
Worker mới
  ↓
Code mới

44. Vì sao phải restart Queue Worker?

Giả sử:

10:00
Deploy Version 1

Worker load:

Version 1

Sau đó:

10:30
Deploy Version 2

Nếu Worker vẫn đang chạy:

Worker
 ↓
Version 1

trong khi website:

Nginx
 ↓
Laravel Version 2

Có thể xảy ra:

Website = Version 2
Worker  = Version 1

Vì vậy deployment cần reload/restart long-running processes.


45. Queue Worker production

Kiến trúc hoàn chỉnh:

                 VPS
                  │
        ┌─────────┴─────────┐
        │                   │
      Nginx              Supervisor
        │                   │
        ▼                   ▼
    PHP-FPM             Queue Worker
        │                   │
        ▼                   ▼
    Laravel 13          Queue Backend
        │
        ▼
      MySQL

Scheduler:

Cron
 │
 ▼
schedule:run
 │
 ▼
Laravel Scheduler

46. Kiểm tra Queue Worker

Trên VPS:

sudo supervisorctl status

Ví dụ:

blog-worker:blog-worker_00    RUNNING
blog-worker:blog-worker_01    RUNNING

Nếu:

STOPPED

kiểm tra:

sudo supervisorctl tail blog-worker:blog-worker_00

hoặc xem log:

tail -f /var/www/blog/storage/logs/worker.log

47. Kiểm tra Queue

Laravel:

php artisan queue:failed

Nếu không có failed jobs:

No failed jobs found.

Nếu có:

ID
Connection
Queue
Class
Failed At

hãy kiểm tra nguyên nhân.


48. Kiểm tra Scheduler

Có thể xem các scheduled tasks bằng:

php artisan schedule:list

Kết quả có thể cho biết:

Command
Frequency
Next Due

Ví dụ:

posts:publish-scheduled    Every Minute
stats:update               Every Hour
reports:generate           Daily

Đây là cách rất hữu ích để kiểm tra xem Scheduler đã nhận configuration chưa.


49. Queue Monitoring

Khi hệ thống lớn, chúng ta cần biết:

Có bao nhiêu Job đang chờ?
Worker có xử lý kịp không?
Queue có bị nghẽn không?

Laravel có:

queue:monitor

để theo dõi queue vượt ngưỡng.

Ví dụ:

php artisan queue:monitor database:default --max=100

Khi queue vượt ngưỡng, Laravel có thể phát sự kiện QueueBusy để ứng dụng phản ứng phù hợp.


50. Redis Queue

Database Queue phù hợp để học và các ứng dụng nhỏ.

Khi hệ thống lớn, Redis thường được sử dụng làm queue backend:

Laravel
   │
   ▼
Redis
   │
   ▼
Worker

.env có thể cấu hình:

QUEUE_CONNECTION=redis

Kiến trúc:

Laravel
   │
   ▼
 Redis
   │
   ├── Job 1
   ├── Job 2
   ├── Job 3
   └── Job 4
         │
         ▼
      Worker

Trong khóa học hiện tại, chúng ta chưa cần triển khai Redis ngay.

Database Queue giúp người mới hiểu bản chất Queue trước.


51. Laravel Horizon

Nếu sử dụng Redis Queue, Laravel có:

Laravel Horizon

Horizon cung cấp giao diện để theo dõi Queue.

Có thể quan sát:

Jobs
Throughput
Runtime
Failed Jobs
Workers

Horizon đặc biệt hữu ích khi ứng dụng có hệ thống Queue lớn.

Trong Blog CMS cơ bản, Horizon có thể xem là phần nâng cao.


52. Queue Worker vs PHP-FPM

Hai thứ này rất dễ nhầm.

PHP-FPM

Xử lý:

HTTP Request

Ví dụ:

GET /blog
POST /login
GET /admin/posts

Queue Worker

Xử lý:

Background Job

Ví dụ:

Send Email
Generate Report
Process Image
Notification

Mô hình:

HTTP
 │
 ▼
Nginx
 │
 ▼
PHP-FPM
 │
 ▼
Laravel

và:

Queue
 │
 ▼
Worker
 │
 ▼
Job

53. Cron vs Laravel Scheduler

Cron

Là cơ chế của hệ điều hành.

Ví dụ:

* * * * * php artisan schedule:run

Laravel Scheduler

Là cơ chế của Laravel.

Ví dụ:

Schedule::command('posts:clean')
    ->daily();

Kết hợp:

Linux Cron
     │
     ▼
schedule:run
     │
     ▼
Laravel Scheduler
     │
     ▼
Task

Laravel giúp chúng ta quản lý lịch chạy trong source code thay vì phải tạo hàng loạt Cron entry.


54. Cấu hình hoàn chỉnh cho Blog CMS

Queue

.env:

QUEUE_CONNECTION=database

Tạo bảng:

php artisan make:queue-table
php artisan migrate

Chạy Worker:

php artisan queue:work

Production:

Supervisor
    ↓
queue:work

Scheduler

routes/console.php:

<?php

use Illuminate\Support\Facades\Schedule;

Schedule::command('posts:publish-scheduled')
    ->everyMinute();

Schedule::command('cleanup:old-data')
    ->dailyAt('02:00');

Cron:

* * * * * cd /var/www/blog && php artisan schedule:run >> /dev/null 2>&1

55. Production Architecture

Sau Bài 48, Blog CMS của chúng ta đã tiến thêm một bước:

                         INTERNET
                             │
                             ▼
                         ┌───────┐
                         │ Nginx │
                         └───┬───┘
                             │
                             ▼
                         PHP-FPM
                             │
                             ▼
                      ┌─────────────┐
                      │ Laravel 13  │
                      └──────┬──────┘
                             │
               ┌─────────────┼─────────────┐
               │             │             │
               ▼             ▼             ▼
             MySQL        Storage        Cache
                             │
                             │
                     ┌───────┴───────┐
                     │               │
                     ▼               ▼
                   Queue         Scheduler
                     │               │
                     ▼               ▼
                  Worker           Cron
                     │
                     ▼
                 Background
                   Jobs

Đây là một architecture production cơ bản nhưng rất thực tế.


56. Checklist Production

Trước khi đưa Queue lên production:

[ ] QUEUE_CONNECTION đã cấu hình

[ ] jobs table tồn tại

[ ] failed_jobs table tồn tại

[ ] Job implements ShouldQueue

[ ] queue:work chạy được

[ ] Supervisor đã cài

[ ] Supervisor configuration đúng

[ ] Worker đang RUNNING

[ ] Worker log hoạt động

[ ] queue:failed kiểm tra được

Scheduler:

[ ] Schedule đã định nghĩa

[ ] schedule:list kiểm tra được

[ ] Cron đã cấu hình

[ ] Cron chạy mỗi phút

[ ] Task không bị overlapping ngoài ý muốn

[ ] Scheduler log/error được kiểm tra

Deployment:

[ ] Code mới đã deploy

[ ] composer install

[ ] migrate --force

[ ] optimize

[ ] queue:restart / reload

[ ] Supervisor tự khởi động Worker mới

57. Bài tập thực hành

Bài tập 1 — Tạo Job

php artisan make:job TestQueueJob

Cho Job ghi log:

Log::info('Queue Job executed');

Dispatch:

TestQueueJob::dispatch();

Sau đó chạy:

php artisan queue:work

Kiểm tra:

storage/logs/laravel.log

Bài tập 2 — Failed Job

Tạo Job cố tình phát sinh exception:

throw new Exception('Test Queue Error');

Sau đó:

php artisan queue:work --tries=1

Kiểm tra:

php artisan queue:failed

Bài tập 3 — Scheduler

Tạo Schedule:

Schedule::call(function () {
    Log::info('Scheduler executed');
})->everyMinute();

Chạy:

php artisan schedule:work

Sau đó kiểm tra:

storage/logs/laravel.log

Bài tập 4 — Supervisor

Cài:

sudo apt install supervisor

Tạo:

/etc/supervisor/conf.d/blog-worker.conf

Khởi động Worker thông qua Supervisor.

Kiểm tra:

sudo supervisorctl status

Bài tập 5 — Production Scheduler

Thêm:

* * * * * cd /var/www/blog && php artisan schedule:run >> /dev/null 2>&1

Sau đó kiểm tra:

php artisan schedule:list

58. Tổng kết

Sau bài này chúng ta đã hiểu hai khái niệm quan trọng:

QUEUE

và:

SCHEDULER

Queue dùng để xử lý:

Background Jobs

Ví dụ:

Email
Notification
Image Processing
Report
API Sync

Scheduler dùng để xử lý:

Timed Tasks

Ví dụ:

Every Minute
Every Hour
Daily
Weekly

Kiến trúc:

             Laravel
                │
        ┌───────┴────────┐
        │                │
      Queue           Scheduler
        │                │
        ▼                ▼
     Worker             Cron
        │                │
        ▼                ▼
       Job              Task

Và trong production:

Supervisor
     │
     ▼
Queue Worker

còn:

Cron
  │
  ▼
schedule:run
  │
  ▼
Laravel Scheduler

📌 Ghi nhớ

Queue

php artisan queue:work

Restart Queue Worker

php artisan queue:restart

Failed Jobs

php artisan queue:failed

Retry

php artisan queue:retry all

Scheduler

php artisan schedule:run

Test Scheduler

php artisan schedule:work

Xem Schedule

php artisan schedule:list

Production

Supervisor
   ↓
Queue Worker

và:

Cron
   ↓
schedule:run

Quan trọng nhất:

Queue = XỬ LÝ VIỆC NỀN

Scheduler = CHẠY VIỆC THEO LỊCH

Khi kết hợp:

Scheduler
    ↓
Dispatch Job
    ↓
Queue
    ↓
Worker
    ↓
Background Processing

thì Laravel 13 có thể xử lý được rất nhiều công việc production mà không bắt người dùng phải chờ trong HTTP request.

Bài tiếp theo: Bài 49 — Production Tips

Chúng ta sẽ hoàn thiện phần triển khai Laravel 13 với:

Cache
Optimize
ENV
APP_DEBUG
Security
Performance
Production Configuration

để Blog CMS sẵn sàng bước sang Bài 50 — Tổng kết dự án Blog CMS.

Không có nhận xét nào:

Đăng nhận xét

Facebook Youtube RSS