Ở 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