Ý chính: Khả năng chịu lỗi không đến từ việc thử lại nhiều hơn, mà từ việc sử dụng ngân sách thời gian và tài nguyên có giới hạn.
Thuật ngữ trong bài: Timeout: thời gian chờ tối đa; Circuit Breaker: tạm ngừng gọi dịch vụ đang lỗi; Bulkhead: tách riêng tài nguyên để một dịch vụ lỗi không kéo theo phần khác.
Bài toán thực tế
Thiếu Timeout khiến yêu cầu giữ tài nguyên quá lâu. Thử lại ở nhiều lớp có thể nhân số lần gọi xuống dưới. Nếu mọi dịch vụ dùng chung một pool kết nối, chỉ một nhà cung cấp chậm cũng có thể làm toàn bộ hệ thống cạn tài nguyên.
Một dịch vụ phụ thuộc chậm có thể giữ hết kết nối và kéo sập cả luồng yêu cầu. Thử lại không giới hạn còn nhân tải đúng lúc hệ thống phía sau yếu nhất.
Mỗi lời gọi cần ngân sách thời gian, số lần thử và nhóm tài nguyên riêng; Circuit Breaker chỉ là lớp cuối để ngăn tiếp tục gọi khi xác suất thành công đã quá thấp.
Thiết kế và triển khai
- Truyền một thời hạn chung từ đầu tới cuối và dừng gọi tiếp khi ngân sách thời gian đã hết.
- Chỉ thử lại lỗi tạm thời trên thao tác an toàn khi lặp, với thời gian chờ tăng dần và số lần giới hạn.
- Cô lập kết nối theo từng dịch vụ phụ thuộc và từ chối sớm trước khi hàng đợi tăng vô hạn.
Mã minh họa: Lời gọi dịch vụ phụ thuộc có ngân sách thời gian
remaining = request.deadline - now()
if remaining < minimumUsefulTime: return degraded()
with bulkhead.acquire(timeout = 20ms):
return retry(max = 2, jitter = true) {
vendor.call(timeout = min(300ms, remaining))
}Tính lại thời gian còn lại trước mỗi lần thử và gắn khóa chống xử lý trùng cho mọi thao tác ghi có thể được thử lại.
Rủi ro cần tính trước
- Dữ liệu dự phòng trong cache đã cũ hơn mức nghiệp vụ cho phép.
- Quá nhiều lời gọi thăm dò làm dịch vụ bên ngoài vừa phục hồi lại quá tải.
- Hệ thống vẫn tiếp tục thử lại sau khi ứng dụng khách đã hủy yêu cầu.
Nên theo dõi gì?
| Tín hiệu | Điều tín hiệu cho biết |
|---|---|
| Phần ngân sách thời gian bị từng dịch vụ sử dụng | Cho biết tích hợp nào đang chiếm phần lớn độ trễ của hành trình. |
| Tỷ lệ khuếch đại do thử lại | Đo tổng số lời gọi xuống dưới trên mỗi yêu cầu nhận vào. |
| Số lần Bulkhead từ chối và trạng thái Circuit Breaker | Cho biết sự cố có được cô lập và quá trình phục hồi có tiến triển hay không. |
Đưa vào production từng bước
Đo độ trễ và số lần gọi hiện tại trước. Thêm timeout rõ ràng nhưng chưa thử lại, sau đó cô lập nhóm kết nối, bật thử lại có giới hạn và cho Circuit Breaker chạy ở chế độ quan sát trước khi áp dụng bắt buộc.
Điều cần nhớ
Tích hợp bền vững giữ sự cố trong giới hạn đã biết và bảo toàn tài nguyên cho phần hệ thống còn khỏe.
