Phân biệt Liveness, Readiness và Startup Probes trong kiểm tra sức khỏe dịch vụ
Bài viết giải thích ba loại kiểm tra sức khỏe quan trọng trong môi trường điều phối container: startup probe, readiness probe và liveness probe. Qua đó giúp dịch vụ microservice hoạt động ổn định, tránh restart không cần thiết và đảm bảo chỉ nhận traffic khi đã sẵn sàng.

Phân biệt Liveness, Readiness và Startup Probes trong kiểm tra sức khỏe dịch vụ
Trong môi trường điều phối container như Kubernetes, việc kiểm tra sức khỏe (health check) của các dịch vụ microservice đóng vai trò rất quan trọng để đảm bảo hệ thống hoạt động ổn định và hiệu quả. Ba loại probe phổ biến — startup probe, readiness probe và liveness probe — phục vụ những mục đích khác nhau nhưng bổ sung cho nhau trong vòng đời của một ứng dụng.
Bài viết này sẽ cùng bạn hiểu rõ từng loại probe, cách cấu hình và ứng dụng phù hợp để dịch vụ Go-based microservice của bạn hoạt động mượt mà, tránh hiện tượng crash loop không cần thiết do bị orchestrator restart quá sớm.
1. Xác định vòng đời của probe
Thay vì xem kiểm tra sức khỏe là một giá trị boolean “đúng/sai” đơn giản, ta cần xem đó là các trạng thái chuyển đổi với mục đích rõ ràng:
- Startup probe: Đánh dấu khoảng thời gian ứng dụng khởi động, tải dữ liệu, chuẩn bị trước khi nhận traffic.
- Readiness probe: Xác nhận ứng dụng đã sẵn sàng tiếp nhận request, các phụ thuộc như database đã kết nối thành công.
- Liveness probe: Kiểm tra ứng dụng đang chạy ổn định, không bị treo hay deadlock, nếu fail sẽ gây restart.
Cấu trúc khai báo Go cho các probe:
type ProbeConfig struct {
Startup Probe `json:"startup"`
Readiness Probe `json:"readiness"`
Liveness Probe `json:"liveness"`
}
type Probe struct {
Enabled bool `json:"enabled"`
Path string `json:"path"`
FailureThreshold int `json:"failureThreshold"`
PeriodSeconds int `json:"periodSeconds"`
}
Thiết kế này giúp tách bạch logic khởi động và sẵn sàng phục vụ traffic, cho phép orchestrator áp dụng chiến lược xử lý phù hợp cho từng trạng thái.
2. Startup probe: Quản lý khởi động ứng dụng
Trong giai đoạn khởi động, dịch vụ thường phải chạy các tác vụ nặng như migrate database hoặc biên dịch JIT. Nếu orchestrator truy vấn probe trong lúc này và nhận trạng thái fail, pod sẽ bị restart liên tục.
Startup probe sẽ yêu cầu orchestrator bỏ qua lỗi trong giai đoạn startup, chỉ cho phép đánh dấu pod sẵn sàng tham gia khi hoàn thành khởi tạo.
Ví dụ Go:
func initHandler(w http.ResponseWriter, r *http.Request) {
if !serverReady {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusOK)
}
Cách làm này tránh việc pod bị kill khi đang tải tài nguyên, giúp khởi động mượt mà hơn.
3. Readiness probe: Kiểm tra sẵn sàng nhận traffic
Readiness probe báo cho orchestrator biết khi nào dịch vụ đã sẵn sàng tiếp nhận request từ người dùng.
Trước khi dịch vụ được đưa vào load balancer, probe này sẽ kiểm tra kết nối với các dịch vụ phụ thuộc như database hoặc cache, tránh việc gửi request đến một dịch vụ chưa thể xử lý.
Mô hình trạng thái:
Startup >----> [Ready?] --> (Startup Done)
| |
v v
(Not Ready) (Readiness Done)
| |
v v
(Restart) [Traffic] --> (Readiness Check)
^ |
| v
(Liveness Check) <--- [Traffic]
Điều này giúp giảm thiểu lỗi timeout và nâng cao trải nghiệm người dùng.
4. Liveness probe: Phát hiện và phục hồi sự cố
Liveness probe giúp phát hiện nếu ứng dụng bị treo hoặc rơi vào trạng thái xấu (ví dụ vòng lặp vô tận, rò rỉ bộ nhớ).
Nếu probe này fail, orchestrator sẽ khởi động lại ứng dụng nhằm dọn dẹp deadlock mà không làm mất các request hiện tại.
Ví dụ xử lý:
func liveHandler(w http.ResponseWriter, r *http.Request) {
if !gcSafe() {
forceGC()
}
w.WriteHeader(http.StatusOK)
}
Đây là cơ chế tự động phục hồi quan trọng trong môi trường sản xuất.
5. Cấu hình ngưỡng thất bại hợp lý
Cấu hình failureThreshold và periodSeconds là rất cần thiết để tránh restart quá mức hoặc chậm xử lý khi xảy ra sự cố.
Ví dụ cấu hình cho phép:
- Startup probe: 5 phút (failureThreshold=30, periodSeconds=10) cho khởi động nặng.
- Readiness và Liveness probe: 30 giây (failureThreshold=3, periodSeconds=10) để phản hồi nhanh.
Cấu hình quá khắt khe dẫn đến restart liên tục gây gián đoạn, còn quá lỏng lẻo thì dịch vụ chậm phục hồi.
6. Kiểm thử tự động và xác thực
Tốt nhất bạn nên mock điều kiện các phụ thuộc để kiểm thử readiness probe hoạt động đúng khi có lỗi.
Ví dụ unit test:
func TestProbeEndpoints(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(liveHandler))
defer server.Close()
assertStatusCode(t, server.URL + "/live", 200)
}
Điều này đảm bảo các probe phản ánh chính xác trạng thái thực tế trong pipeline CI/CD.
Tóm lại
- Xem probe là trạng thái chuyển đổi, không phải boolean đơn giản
- Startup probe giúp tránh restart khi đang khởi động
- Readiness probe khóa lưu lượng đến dịch vụ chưa sẵn sàng
- Liveness probe phát hiện kịp thời để tự động restart
- Kiểm tra các phụ thuộc ngoài như database trong probe
- Cấu hình ngưỡng phù hợp để cân bằng ổn định và phản hồi
Hướng phát triển tiếp theo
- Kết nối probe với hệ thống monitoring để theo dõi thành công và độ trễ
- Tìm hiểu chính sách backoff mặc định của nhà cung cấp orchestration
- Thêm các probe kiểm tra queue depth hoặc thread pool với ứng dụng xử lý đồng thời cao
- Kiểm toán log ứng dụng để đảm bảo cảnh báo probe khớp với nguyên nhân gốc rễ
Tham khảo thêm
- Designing Data-Intensive Applications (Kleppmann) — Hiểu yêu cầu độ tin cậy của data store tương tác với probe.
- A Philosophy of Software Design (Ousterhout) — Lý do tách biệt logic probe khỏi nghiệp vụ chính giúp giảm phức tạp.
Bài viết nằm trong series về Kiến trúc phần mềm hiện đại hỗ trợ lập trình viên và kỹ sư DevOps xây dựng hệ thống microservice ổn định, linh hoạt.
Bài viết liên quan

AI & Machine Learning
Câu chuyện về người đàn ông Philippines xây dựng "AI bất tử" bằng cách khai thác miễn phí 11 nền tảng công nghệ
18 tháng 4, 2026

Phần mềm
Chuyển nhà từ DigitalOcean sang Hetzner: Giảm chi phí từ $1,432 xuống $233 với Zero Downtime
18 tháng 4, 2026

Phần mềm
AI Agents Cần "Bàn Làm Việc" Riêng: Giải Pháp Từ Git Worktrees
18 tháng 4, 2026
