Chào mừng
Chào mừng
Một đội máy (fleet) quy mô web chứa nhiều máy. Tại bất kỳ thời điểm nào, một số máy khỏe mạnh, một số đang khởi động, một số đang rút bớt tải (draining), và một số đang bị hỏng một cách im lặng. Đội máy tồn tại được trong điều kiện này vì mỗi máy đều trả lời hai câu hỏi đơn giản khi được yêu cầu:
- /health — tôi hiện tại có khả năng xử lý các yêu cầu thực không?
- /version — tôi đang chạy mã nguồn (code) nào?
Cùng với một endpoint đo lường (thường là /metrics) để hiển thị các bộ đếm (counters) & đồng hồ đo (gauges) cho các công cụ giám sát thu thập (scrape).
Bài học này hướng dẫn cách thiết kế các endpoint này để chúng thực sự phản ánh thực tế, ý nghĩa của bốn tín hiệu vàng (four golden signals) ở tầng proxy, & cách dữ liệu quan sát được thúc đẩy các quyết định về năng lực xử lý (capacity).
Vào cuối bài học, bạn sẽ:
- Thiết kế một endpoint /health phát hiện sự cố thực sự trên đường dẫn (path), chứ không chỉ là sự sống còn của tiến trình (process liveness)
- Thiết kế một endpoint /version cho phép bạn xác minh một lần triển khai (deploy) đã được thực hiện thành công
- Áp dụng bốn tín hiệu vàng (độ trễ, lưu lượng, lỗi, độ bão hòa) ở tầng proxy
- Liên kết các chỉ số tăng đột biến (surge metrics) quan sát được với các quyết định về năng lực xử lý: khi nào nên mở rộng (scale up), khi nào nên rút bớt (drain), khi nào nên gọi hỗ trợ khẩn cấp (page)
- Suy luận về SLO & tốc độ tiêu hao ngân sách lỗi (error budget burn rate) như một kỷ luật vận hành đằng sau câu hỏi "chúng ta quan tâm đến mức độ nào?"
Hai loại kiểm tra sức khỏe
Liveness so với Readiness
Liveness: tiến trình có đang sống không? Được các trình điều phối (Kubernetes, systemd) sử dụng để quyết định xem có nên khởi động lại tiến trình hay không.
Readiness: tiến trình có sẵn sàng xử lý lưu lượng thực tế ngay bây giờ không? Được các bộ cân bằng tải sử dụng để quyết định xem có nên gửi yêu cầu hay không.
Đây là những câu hỏi khác nhau. Một tiến trình đang sống nhưng không thể kết nối đến cơ sở dữ liệu của nó thì đang sống nhưng chưa sẵn sàng. Một tiến trình đang khởi động thì đang sống nhưng chưa sẵn sàng.
Kiểm tra sức khỏe nông so với sâu
Nông: trả về {"status": "ok"} nếu trình xử lý HTTP chạy được. Rất đơn giản. Chỉ phát hiện được khi tiến trình bị dừng.
Sâu: thực sự kiểm tra đường dẫn yêu cầu thực tế. Kiểm tra xem nhóm kết nối cơ sở dữ liệu có thể trả về một kết nối không, bộ nhớ đệm có thể truy cập được không, và các phụ thuộc hạ nguồn có phản hồi không. Phát hiện các sự cố chức năng mà các kiểm tra nông bỏ sót.
Sự đánh đổi: các kiểm tra sâu tốn kém hơn (mỗi kiểm tra về cơ bản là một yêu cầu tổng hợp) & có thể gây ra sự cố dây chuyền (nếu kiểm tra sức khỏe của mọi bản sao đều dồn dập truy vấn cơ sở dữ liệu, một cơ sở dữ liệu chậm sẽ khiến tất cả các bản sao bị coi là không khỏe, điều này loại bỏ chúng khỏi vòng quay, và kết quả là toàn bộ năng lực xử lý bị mất).
Thực hành tốt nhất: một kiểm tra nông cho tính sống sót (nhanh, rẻ, không có phụ thuộc bên ngoài) & một kiểm tra sâu hơn cho tính sẵn sàng (kết quả được lưu trong bộ nhớ đệm, được giới hạn tần suất để tránh dồn dập truy vấn các hệ thống hạ nguồn).
Các Endpoint Phiên bản
/version trả về commit git, thời gian build & tên dịch vụ. Sau khi triển khai, bạn curl https://service.example.com/version & xác nhận commit được trả về khớp với commit bạn đã đẩy lên. Nếu không khớp, việc triển khai đã thất bại một cách im lặng.
Không có /version, một bản triển khai lỗi thời có thể trông như thành công & ẩn nấp trong nhiều giờ.
Hình dạng phản hồi tối thiểu: {"service": "my-api", "git_commit": "abc1234", "build_time": "2026-05-19T10:00:00Z"}.
Độ trễ, Lưu lượng, Lỗi, Bão hòa
Bốn Con Số Bao Phủ Phần Lớn Hoạt Động Vận Hành
Từ cuốn sách Google SRE. Bốn tín hiệu bạn đo lường trên mọi tầng dịch vụ. Nếu bạn đo lường bốn tín hiệu này tốt, bạn sẽ phát hiện phần lớn các sự cố trong môi trường sản xuất trước khi người dùng nhận thấy.
Độ trễ (Latency): một yêu cầu mất bao lâu để hoàn thành? Hãy báo cáo phân phối (distribution), không chỉ giá trị trung bình. p99 (độ trễ ở phân vị 99) quan trọng hơn giá trị trung bình, vì độ trễ ở phần đuôi (tail latency) chính là thứ người dùng cảm nhận là 'chậm'. Một dịch vụ có độ trễ trung bình 50 ms nhưng p99 là 5.000 ms đang gặp vấn đề thực sự mà hầu hết người dùng không bao giờ nhận ra, nhưng 1% người dùng bị ảnh hưởng nặng nhất chắc chắn sẽ cảm nhận được.
Lượng truy cập (Traffic): có bao nhiêu yêu cầu mỗi giây? Tổng số yêu cầu, theo từng endpoint, theo mã trạng thái, theo từng khu vực. Nền tảng (baseline) đã được xác định; cảnh báo khi có bất thường (giảm đột ngột = vấn đề ở lớp ingress; tăng đột ngột = đột biến lưu lượng hoặc tấn công).
Lỗi (Errors): tỷ lệ yêu cầu thất bại. Phân biệt 4xx (lỗi phía client, không phải lỗi của bạn) với 5xx (lỗi phía server, lỗi của bạn). Theo dõi tỷ lệ lỗi dưới dạng phần trăm của lượng truy cập, không phải số lượng tuyệt đối, để cảnh báo hoạt động hiệu quả ở mọi mức tải.
Bão hòa (Saturation): hệ thống đã đầy đến mức nào? Tận dụng CPU, bộ nhớ, độ sâu của pool kết nối, độ dài hàng đợi. Đây là chỉ báo đi trước (leading indicator). Mức bão hòa tăng lên trước khi độ trễ hoặc lỗi bị suy giảm. Một tầng (tier) ở mức bão hòa 90% chỉ cách sự sụp đổ của hàng đợi đúng một phút tồi tệ.
Cụ thể tại tầng Proxy
Mỗi tín hiệu đều được bật sáng (hiển thị rõ) ở lớp biên (edge layer):
- Độ trễ tại proxy: thời gian bắt tay TLS (TLS handshake), thời gian kết nối upstream, tổng thời gian yêu cầu-phản hồi. Được đo lường riêng biệt vì chúng nằm ở các phần khác nhau của đường dẫn.
- Lượng truy cập tại proxy: tổng số yêu cầu/giây, phân phối theo từng backend (một backend 'nóng' báo hiệu sự lệch pha của bộ cân bằng tải), phân tách theo mã trạng thái.
- Lỗi tại proxy: 4xx từ client (người dùng của bạn truy cập các endpoint không hợp lệ), 5xx từ backend (các dịch vụ của bạn gặp sự cố), lỗi nội bộ của proxy (502 = không thể kết nối tới backend, 504 = backend bị hết thời gian chờ).
- Bão hòa tại proxy: số lượng phiên TLS, độ sâu của pool kết nối upstream, CPU của chính proxy (việc kết thúc TLS tiêu tốn nhiều CPU).
Mẹo chuyên gia: sự gia tăng đột ngột các mã 502 kèm theo độ trễ backend thấp có nghĩa là backend đang ngắt kết nối trước khi phản hồi (reset kết nối, crash, hết bộ nhớ). Sự gia tăng các mã 504 có nghĩa là backend đang chậm nhưng vẫn đang phản hồi. Hãy đọc mã lỗi; nó cho bạn biết sự cố nằm ở đâu.
Đọc các Tín hiệu
Dashboard của bạn hiển thị các thông tin sau trong 10 phút qua:
- Lưu lượng: tương đối ổn định ở mức 800 req/s (không có đột biến)
- Độ trễ: p50 ổn định ở mức 40ms, p99 tăng từ 200ms lên 2.500ms trong 5 phút & vẫn đang tiếp tục tăng
- Lỗi: Tỷ lệ 4xx ổn định ở mức 0,3% (nền bình thường); tỷ lệ 5xx tăng từ 0,1% lên 1,2% (chủ yếu là 504 Gateway Timeout)
- Bão hòa: CPU phía backend tăng từ 45% lên 78% trong cùng 5 phút đó; CPU proxy ổn định ở mức 30%
Khi nào mở rộng, khi nào rút bớt, khi nào gọi người trực
Các quyết định về dung lượng cần có kích hoạt
Việc quan sát các chỉ số là dễ dàng. Biết được khi nào cần hành động dựa trên chúng mới là kỷ luật thực sự.
Mở rộng khi: mức bão hòa vượt qua ngưỡng duy trì (ví dụ: CPU backend >70% trong 5 phút), hoặc độ sâu hàng đợi vượt quá mục tiêu, hoặc độ trễ p99 vượt quá SLO. Kích hoạt phải được kích hoạt trước khi hệ thống bị lỗi, chứ không phải tại thời điểm nó bị lỗi.
Rút bớt một bản sao khi: nó liên tục chậm / có lỗi trong khi các bản sao khác hoạt động bình thường (một bản sao chạy nóng thường là vấn đề ở cấp độ máy chủ, không phải vấn đề ứng dụng), hoặc khi triển khai phiên bản mới, hoặc khi ngừng hoạt động một bản sao một cách an toàn.
Gọi người trực khi: SLO đang bị vi phạm nhanh hơn mức ngân sách lỗi có thể chịu đựng, hoặc kích hoạt bão hòa được kích hoạt nhưng tự động mở rộng không thể hấp thụ nó, hoặc xuất hiện mô hình lan truyền (cả tỷ lệ lỗi và tỷ lệ thử lại đều tăng).
Không gọi người trực khi: một phút hoạt động kém duy nhất tự khắc phục, hoặc các tác vụ hàng loạt nền gây ra các dao động định kỳ như mong đợi, hoặc nhiễu vượt qua ngưỡng (ngưỡng là sai, không phải hệ thống).
SLO & Tốc độ tiêu hao ngân sách lỗi
SLO (mục tiêu mức dịch vụ) định nghĩa hiệu suất chấp nhận được: 'tỷ lệ thành công >= 99,9% trong cửa sổ 28 ngày'. Phần bù (0,1%) là ngân sách lỗi.
Tốc độ tiêu hao (Burn rate): tốc độ bạn đang tiêu thụ ngân sách lỗi. Nếu bạn tiêu hao 10% ngân sách trong 1 giờ, tốc độ này nhanh hơn mức bền vững 240 lần (1 giờ là 1/672 của cửa sổ 28 ngày; tiêu hao 10% trong cửa sổ đó = 10% × 672 = 6720% dự kiến cho toàn bộ cửa sổ, trong khi chỉ cho phép 100%).
Cảnh báo tốc độ tiêu hao đa cửa sổ: kích hoạt cảnh báo (page) khi cả cửa sổ ngắn (5 phút với tốc độ 14,4 lần) & cửa sổ dài (1 giờ với tốc độ 6 lần) đều tiêu hao nhanh hơn mức bền vững. Phát hiện cả sự cố nhanh & suy giảm chậm.
Tại sao điều này quan trọng đối với năng lực: một dịch vụ chạy ở SLO 99,9% với 1% dư địa có thể hấp thụ các sự cố nhỏ. Một dịch vụ ở 99,93% (vừa đủ đáp ứng SLO) chỉ cần một ngày xấu là vi phạm. Các quyết định về năng lực nên hướng tới biên độ SLO thoải mái, không phải mức tối thiểu để đáp ứng.
Một Quyết Định Về Năng Lực Dưới Sự Quan Sát
Dịch vụ của bạn có SLO là 99,9% yêu cầu thành công trong 28 ngày. Trạng thái hiện tại từ giám sát trong 1 giờ qua:
- Tỷ lệ thành công: 99,5% (duy trì trong 30 phút)
- CPU phía sau (Backend): trung bình 82% trên toàn bộ cụm (mục tiêu 70%)
- Độ trễ p99: 800 ms (mục tiêu SLO: <500 ms)
- Lưu lượng: 1.400 req/s, tăng từ mức cơ sở 1.000 req/s (cao hơn mức bình thường 40%; xu hướng vẫn đang tăng)
- Tự động mở rộng (Autoscaling): được cấu hình để thêm bản sao (replicas) khi CPU > 80% duy trì trong 5 phút; hiện đang trong quá trình mở rộng sẽ thêm 3 bản sao trong ~90 giây
Thiết kế Kế hoạch Quan sát (Observability) cho Việc Ra Mắt
Tổng hợp
Bạn giờ có thể thiết kế một /health để bắt các sự cố thực tế, một /version để xác minh các lần triển khai, các bảng điều khiển bốn tín hiệu vàng ở tầng proxy, & các bộ kích hoạt dung lượng gắn với tốc độ đốt SLO.
Áp dụng cả bốn.
Đội ngũ của bạn đang ra mắt search.example.com (dịch vụ tìm kiếm từ bài học về các chế độ lỗi). Đội ngũ muốn triển khai khả năng quan sát (observability) để bắt các vấn đề trước khi người dùng nhận thấy, kèm theo một ma trận quyết định rõ ràng về việc có nên cảnh báo (page) hay không. SLO: 99,9% yêu cầu thành công, độ trễ p99 < 300 ms, trong cửa sổ 28 ngày.
Kết thúc Khóa học
Kết thúc Khóa học
Bạn đã hoàn thành cả năm bài học:
- Proxy & Nguồn gốc (Origins): hình dạng của lớp biên (edge-layer) mà hầu hết các dịch vụ web công khai đều sử dụng
- Mở rộng ngang không trạng thái (Stateless Horizontal Scaling): lý do tại sao tầng không trạng thái có thể nhân bản với chi phí thấp & cách để xác định kích thước cho nó
- Tách biệt Ingress & Egress: lý do một máy chủ trở thành hai, & chế độ lỗi (failure mode) buộc phải thực hiện điều này
- Chế độ lỗi & Bán kính ảnh hưởng (Blast Radius): các điểm lỗi đơn (SPOFs), sự lan truyền lỗi (cascades), bài học sau sự cố (postmortems), các mục hành động không đổ lỗi (blameless action items)
- Khả năng quan sát & Dung lượng (bài này): những gì cần đo lường để các vấn đề lộ ra trước khi người dùng nhận thấy
Dây chuyền xuyên suốt: một hệ thống phân tán quy mô web không phải là phép thuật. Nó là một tập hợp nhỏ các mẫu thiết kế (reverse proxy, bản sao không trạng thái, tách ingress/egress, bulkheads & circuit breakers, bốn tín hiệu vàng) được kết hợp một cách có chủ đích. Một khi bạn nhận ra các mẫu này, bạn sẽ thấy chúng trong mọi kiến trúc sản xuất.
Các bài học đồng hành: năm bài học về hình học-* tái diễn đạt cùng nội dung dưới dạng lý thuyết đồ thị & hình học. Chúng phù hợp khi học theo bất kỳ thứ tự nào.
Làm tốt lắm.