Lập trình · 22/09/2026

Học Laravel 13 – Bài 35: Monitoring, health check và kiểm chứng backup Laravel

Bài 35 — Monitoring, health check và backup: Ứng dụng còn trả HTTP không có nghĩa worker đang xử lý job, scheduler chạy đúng giờ hoặc backup khôi phục được. TaskFlow cần những tín hiệu riêng cho từng cam kết, cùng người chịu trách nhiệm xử lý khi cảnh báo xuất hiện.

Học Laravel 13 – Bài 35: Monitoring, health check và kiểm chứng backup Laravel

Bài 35 — Monitoring, health check và backup: Ứng dụng còn trả HTTP không có nghĩa worker đang xử lý job, scheduler chạy đúng giờ hoặc backup khôi phục được. TaskFlow cần những tín hiệu riêng cho từng cam kết, cùng người chịu trách nhiệm xử lý khi cảnh báo xuất hiện.

1. Phân biệt sống, sẵn sàng và hoàn tất nghiệp vụ

/up mặc định kiểm tra ứng dụng boot được, không kiểm tra toàn bộ dependency. taskflow:health-check là lệnh CLI nội bộ bổ sung SELECT 1, cache ghi/đọc và private storage ghi/đọc. Worker process còn sống vẫn có thể nghe sai queue; timer active vẫn có thể bỏ lỡ nghiệp vụ. Giám sát phải nhìn kết quả hoàn tất, không chỉ PID.

Tín hiệuCâu hỏiPhản ứng
HTTP lỗi/p95Người dùng có nhận kết quả đúng hạn?Đối chiếu release, log đã lọc, database
Tuổi job chờ/failed jobsQueue có tiến triển?Kiểm tra đúng worker và dependency trước retry
Heartbeat tác vụLịch dự kiến có hoàn tất?Kiểm tra timer, lock, múi giờ và exit code
Tuổi backup/restore gần nhấtCó dữ liệu phục hồi và đã thử?Kiểm tra pipeline backup và diễn tập restore

Đặt ngưỡng và cửa sổ cảnh báo theo SLO của hệ thống, không sao chép con số tùy ý. Mỗi cảnh báo cần owner, mức ưu tiên, kênh liên hệ và runbook. Khóa học chưa kết nối nhà cung cấp monitoring hoặc gửi cảnh báo thật.

2. Health check không lộ secret

php artisan taskflow:health-check
php artisan taskflow:security-check

Lệnh thứ nhất kiểm tra dependency; lệnh thứ hai kiểm tra cấu hình an toàn. Không dùng chúng thay nhau. Health check in PASS/FAIL theo nhãn và trả exit code khác 0 khi lỗi. Nó không in exception gốc vì chuỗi lỗi kết nối có thể chứa credential hoặc đường dẫn.

// Excerpt from HealthCheck; each closure is caught independently by the command.
'database' => fn () => DB::select('select 1') !== [],
'cache' => function (): bool {
    $key = 'taskflow:health:'.Str::uuid();
    try {
        return Cache::put($key, 'probe', 30) && Cache::get($key) === 'probe';
    } finally {
        Cache::forget($key);
    }
},

HealthCheck import các facade DB/Cache/Storage và Str. Probe storage dùng UUID dưới .health trên disk local private, đọc lại rồi xóa đúng file vừa tạo trong finally. Cache dùng key riêng với TTL 30 giây, không flush toàn bộ store. Đây là probe có ghi nhỏ, không phải lệnh hoàn toàn read-only. Nếu process bị kill, file thử có thể còn lại; chỉ dọn sau khi xác nhận tuổi và nguồn gốc.

Chạy bằng cùng identity/environment với ứng dụng. Array cache pass không chứng minh cache chia sẻ hoạt động; quyền của deploy user không chứng minh FPM có quyền tương tự. Cấu hình timeout cho client database/cache và deadline ở process monitor: lệnh chưa có timeout tổng. Không đưa CLI thành endpoint debug public và không dùng một dependency chập chờn để restart toàn bộ fleet liên tục.

3. Backup bắt đầu từ yêu cầu phục hồi

RPO là mức mất ghi có thể chấp nhận; RTO là thời gian phục hồi mục tiêu. Hai giá trị cần được thống nhất trước khi chọn lịch, retention và nơi lưu. Với TaskFlow phải tính database, PDF private, APP_KEY/secret cần thiết trong kho bí mật riêng và code/lockfile tương ứng. Mất key có thể khiến dữ liệu mã hóa không đọc được dù database còn nguyên.

Database metadata và file không nằm trong một transaction. Chọn thời điểm tạm ngừng ghi có kiểm soát hoặc cơ chế snapshot nhất quán, sau đó đối soát tham chiếu. Mã hóa backup, giới hạn quyền, giữ bản ngoài host và thiết kế chống xóa theo yêu cầu. Không lưu backup dưới public hoặc in secret vào log.

4. Diễn tập SQLite cô lập

BackupRestoreDrillTest tạo schema trong SQLite bộ nhớ, một task và attachment fixture. Nó tạo snapshot bằng VACUUM INTO, mở bản phục hồi ở đường dẫn khác rồi kiểm tra integrity, foreign key, title, task_id, size và SHA-256 của file đã phục hồi. Mọi đường dẫn nằm trong fake disk của test; không đọc database phát triển/production.

// Inside BackupRestoreDrillTest, after migrating isolated in-memory SQLite:
$disk = Storage::fake('restore-drill');
$snapshot = $disk->path('snapshot.sqlite');
DB::statement('VACUUM INTO '.DB::getPdo()->quote($snapshot));
$disk->copy('snapshot.sqlite', 'restored.sqlite');
$restored = new PDO('sqlite:'.$disk->path('restored.sqlite'));
$this->assertSame('ok', $restored->query('PRAGMA integrity_check')->fetchColumn());
$this->assertSame([], $restored->query('PRAGMA foreign_key_check')->fetchAll());

Đây là trích đoạn, không phải script backup production. VACUUM INTO tạo snapshot sang file mới, không ghi đè database nguồn; destination phải mới hoặc rỗng. Không chạy khi connection còn transaction mở. Snapshot database không bao gồm filesystem; test copy file riêng và đối chiếu checksum. Không copy mù file SQLite đang chạy rồi bỏ qua WAL. MySQL/PostgreSQL phải dùng công cụ và kế hoạch phục hồi tương ứng.

5. Checklist restore trước khi kết nối lại dịch vụ

  1. Chọn backup và code tương ứng, chuẩn bị database/storage đích mới.
  2. Cô lập mạng gửi mail/webhook, tắt scheduler/worker/Reverb đến khi review xong.
  3. Restore database/file/secret an toàn; kiểm tra integrity, số bản ghi và mẫu attachment.
  4. Boot ứng dụng, thử login/policy/task và download file có quyền; kiểm tra giải mã nếu có.
  5. Quyết định job nào được replay; tránh gửi lại email hoặc thực hiện tác dụng phụ ngoài ý muốn.
  6. Xử lý session/token được phục hồi: backup có thể làm sống lại credential đã revoke sau thời điểm snapshot.
  7. Ghi thời gian thực tế, checkpoint phục hồi, mức mất ghi ước tính và người nghiệm thu.

Không restore đè production chỉ để “thử”. Exit 0 của tác vụ backup hoặc checksum khớp chưa chứng minh ứng dụng phục hồi được. Sau diễn tập, chỉ xóa dữ liệu thử đã xác định; không dùng lệnh dọn broad path.

6. Bằng chứng hiện tại

php artisan test --filter=HealthCheckTest
php artisan test --filter=BackupRestoreDrillTest
php artisan test
vendor/bin/pint --test

Toàn suite đạt 102 tests/465 assertions và Pint pass. Health test kiểm tra thành công, lỗi DB không lộ exception, cache trả sai; restore test kiểm tra dữ liệu/file fixture. Chưa kiểm chứng WAL có tải đồng thời, backup offsite mã hóa, phục hồi key, boot HTTP từ bản restore, dữ liệu lớn, RPO/RTO hoặc lịch backup tự động. Tài liệu vận hành nằm trong taskflow/deploy/monitoring-backup.md.

Bài tập: lập bảng SLO/owner cho từng tín hiệu, diễn tập dependency mất kết nối trên staging và lưu báo cáo restore gồm cả điều chưa đạt. Bài tiếp theo là quản lý dependency và nâng cấp Laravel có kiểm soát.

Tham khảo: SQLite VACUUM INTO, Laravel deployment và health route. Điều hướng: Bài 34 · Lộ trình.

Điều hướng khóa học Laravel 13

Bài trước (34) · Bài sau (36) · Mục lục trọn bộ 37 bài

Thảo luận

Bình luận 0

Đăng nhập để bình luận

Bạn cần có tài khoản để tham gia thảo luận và trả lời độc giả khác.

Đăng nhậpĐăng ký

Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.