Các Mẫu Thiết kế Độ Ổn định Hệ thống (Stability Patterns)

Hệ thống 7 mẫu thiết kế độ ổn định kinh điển (Michael Nygard & Erlang) giúp chặn đứng sự cố sụp đổ dây chuyền: Timeouts, Circuit Breaker, Fail Fast, Bulkheads, Let-It-Crash, Steady State, Throttling & Backpressure.

stabilitycircuit-breakertimeoutsbulkheadlet-it-crashbackpressurethrottlingresilience
Cập nhật: 23 tháng 10, 2026

Tại sao Độ Ổn định (Stability) là Sống còn?

Một hệ thống có khả năng mở rộng đến hàng nghìn máy chủ (Scalability) vẫn có thể sụp đổ hoàn toàn trong tích tắc nếu một sự cố cục bộ kích hoạt phản ứng dây chuyền không kiểm soát (cascading failure).

⚠️ Chân lý Vận hành Hệ thống Phân tán:

"Một phản hồi chậm nguy hiểm hơn rất nhiều so với một lỗi từ chối tức thời!"
Khi một dịch vụ hạ nguồn bị treo, các luồng xử lý ở dịch vụ thượng nguồn sẽ bị khóa chặt trong trạng thái chờ, nhanh chóng rút cạn toàn bộ bể luồng (thread pool), bể kết nối (connection pool) và kéo sập toàn bộ hệ sinh thái.

Kế thừa cuốn sách kinh điển "Release It!" của Michael Nygard và kiến trúc chịu lỗi của Erlang, Jonas Bonér hệ thống hóa 7 Mẫu Thiết kế Độ Ổn định Cốt lõi.

Bảng Tổng hợp 7 Mẫu Thiết kế Độ Ổn định

Mẫu Thiết kếCơ chế Kỹ thuậtRủi ro Triệt tiêuVị trí Áp dụng
1. TimeoutsĐặt giới hạn thời gian chờ tường minh 4 ngưỡng: connect (1s), read (2s), write (2s), pool (0.5s).Ngăn các luồng bị treo vô hạn rút cạn CPU và kết nối.Mọi cuộc gọi mạng HTTP/RPC và truy vấn DB.
2. Circuit BreakerMáy trạng thái Closed → Open → Half-Open ngắt cuộc gọi khi tỷ lệ lỗi vượt ngưỡng.Chống sụp đổ dây chuyền, tạo thời gian cho dịch vụ đích tự hồi phục.Cổng tích hợp API bên thứ ba, giao tiếp giữa các microservices.
3. Fail FastKiểm tra tính sẵn sàng của tài nguyên và dữ liệu đầu vào ngay tại cửa ngõ trước khi xử lý.Tránh lãng phí tài nguyên cho các yêu cầu chắc chắn thất bại.API Gateway, Controller, trước khi mở transaction.
4. BulkheadsPhân tách các bể luồng, bể kết nối độc lập theo từng nghiệp vụ (như vách ngăn kín nước thân tàu).Ngăn sự cố ở dịch vụ phụ (ví dụ Báo cáo) làm sập dịch vụ chính (Thanh toán).Connection pool, Thread pool của từng module.
5. Let-It-CrashKhông bắt lỗi phòng vệ rối rắm; để tiến trình/Actor sập và khôi phục qua Supervisor Hierarchies.Loại bỏ trạng thái bộ nhớ bị nhiễm bẩn (corrupted state), tự động hóa khôi phục.Hệ thống Actor (Akka, Erlang), container Pod trong Kubernetes.
6. Steady StateỨng dụng tự dọn dẹp (clean up after you), giới hạn cache, xoay vòng nhật ký (RollingFileAppender).Chống tràn ổ đĩa (100% disk), rò rỉ bộ nhớ (memory leaks) và tràn RAM (OOM).Cấu hình Logging, quản lý tài nguyên nền.
7. Throttling & BackpressureGiới hạn tốc độ (Rate Limiting) và phát tín hiệu áp lực ngược yêu cầu bên gửi giảm tốc.Chống quá tải đột biến (traffic bursts, DDoS), duy trì nhịp độ xử lý ổn định.API Gateway, hàng đợi SEDA, Reactive Streams.

Circuit Breaker: Máy Trạng thái và Phục hồi Lưu lượng

Circuit Breaker hoạt động tương tự như một cầu dao điện tự động trong gia đình:

Đang tải sơ đồ...

Thông lượng Request Hợp lệ qua Các Giai đoạn Chuyển mạch của Circuit Breaker:

* Giai đoạn 1-2: Closed (100% throughput) → Giai đoạn 3-5: Open ngắt mạch (0% throughput, fail fast) → Giai đoạn 6: Half-Open thử nghiệm → Giai đoạn 7-8: Phục hồi hoàn toàn.

Quy tắc Thử lại An toàn (Retries với Jitter):

Khi kết hợp Timeouts và Retries, tuyệt đối không thử lại ngay lập tức hoặc thử lại theo chu kỳ cố định (gây ra hiện tượng bầy đàn - Thundering Herd). Bắt buộc phải áp dụng thuật toán Exponential Backoff and Jitter: Delay = Min(Max_Delay, Base × 2^attempt) + Random_Jitter.

Triết lý Let-It-Crash & Supervisor Hierarchies

Thay vì viết hàng nghìn dòng try...catch phòng vệ rối rắm để bắt mọi lỗi không lường trước — một việc thường giữ tiến trình sống lay lắt với bộ nhớ đã bị hỏng — triết lý Let-It-Crash của Erlang và Akka chấp nhận lỗi là một phần tự nhiên của vòng đời phần mềm.

Khi một Actor con bị sập, Cây Giám sát (Supervisor Hierarchies) sẽ can thiệp thông qua hai chiến lược khởi động lại:

Đang tải sơ đồ...
  • OneForOne Strategy: Chỉ khởi động lại đúng Actor con bị sập về trạng thái sạch ban đầu. Áp dụng khi các tác vụ con độc lập hoàn toàn với nhau.
  • AllForOne (OneForAll) Strategy: Dừng và khởi động lại toàn bộ các Actor con cùng cấp khi một Actor sập. Bắt buộc áp dụng khi các tác vụ con có mối quan hệ phụ thuộc chặt chẽ mà sự sụp đổ của một mắt xích làm mất tính đúng đắn của toàn bộ chuỗi.

Cài đặt Mẫu Circuit Breaker

Triển khai đơn giản máy trạng thái Circuit Breaker trong Python:

circuit_breaker.py
import time
import random

class CircuitBreaker:
    def __init__(self, failure_threshold=5, cooldown_period=30):
        self.state = "CLOSED"  # CLOSED, OPEN, HALF-OPEN
        self.failure_count = 0
        self.failure_threshold = failure_threshold
        self.cooldown_period = cooldown_period
        self.last_state_change = time.time()

    def call(self, func, *args, **kwargs):
        now = time.time()
        
        # Kiểm tra chuyển từ OPEN sang HALF-OPEN
        if self.state == "OPEN":
            if now - self.last_state_change > self.cooldown_period:
                print("⚡ Circuit Breaker chuyển sang HALF-OPEN: Thử nghiệm dịch vụ...")
                self.state = "HALF-OPEN"
                self.last_state_change = now
            else:
                raise Exception("🚫 Circuit Breaker OPEN: Dịch vụ đang bị ngắt mạch (Fail Fast)!")

        try:
            result = func(*args, **kwargs)
            # Thành công: Nếu ở HALF-OPEN thì đóng mạch lại
            if self.state == "HALF-OPEN":
                print("✅ Dịch vụ đã phục hồi! Đóng mạch (CLOSED).")
                self.state = "CLOSED"
                self.failure_count = 0
                self.last_state_change = now
            return result
        except Exception as e:
            self.failure_count += 1
            print(f"❌ Lỗi ghi nhận ({self.failure_count}/{self.failure_threshold}): {e}")
            
            if self.state in ["CLOSED", "HALF-OPEN"] and self.failure_count >= self.failure_threshold:
                print("🔥 Vượt ngưỡng lỗi! Mở mạch Circuit Breaker (OPEN).")
                self.state = "OPEN"
                self.last_state_change = now
            raise e

Các Trang Liên quan