← Series hub ← Prev

Bài 5: Quan sát hệ thống (Observability) - Bắt bệnh giữa “Rừng” Microservices

Bạn là một kĩ sư trực hệ thống đêm 11.11. Đột nhiên app báo lỗi: Tỉ lệ thanh toán thành công giảm mạnh, người dùng bị Timeout liên tục. Trong một hệ thống nguyên khối (Monolithic) xưa cũ, bạn mở file error.log ra và tìm thấy ngay lỗi dòng code. Tuy nhiên, ở Shopee, vòng đời của một nút bấm “Thanh Toán” phải nhảy qua 30 dịch vụ: API Gateway -> Order Service -> Promo Service -> Inventory Service -> Payment Service -> Banking Gateway...

Nếu lỗi hoặc nghẽn (latency spike) xảy ra ở service thứ 25, làm sao tìm ra nó giữa hàng vạn Pods đang chạy? Lời giải nằm ở 3 trụ cột của Observability: Metrics, Logs, và Distributed Tracing.

1. Truy vết phân tán (Distributed Tracing)

Công cụ cốt lõi để vẽ nên “bản đồ đường đi” của request chính là Distributed Tracing (Shopee sử dụng các nền tảng dựa trên OpenTelemetry / Jaeger).

  • Trace ID: Ngay tại giây phút request của người dùng chạm tới API Gateway, Gateway sẽ tự động tạo ra một chuỗi định danh duy nhất (Ví dụ: TraceID: a8f9x0).
  • Context Propagation: Chìa khóa của Tracing là TraceID này sẽ được chèn vào Metadata/Header của mọi gRPC call tiếp theo. Order Service gọi Promo Service cũng kèm theo TraceID đó.
  • Span ID: Mỗi khi request chui vào và chui ra khỏi một Service, nó tạo thành 1 block thời gian gọi là Span. Kết quả, hệ thống gom toàn bộ dữ liệu này lại, vẽ lên một biểu đồ thác nước (Waterfall), chỉ rõ ràng cho Dev thấy: Tới Inventory mất 5ms, nhưng kẹt ở Payment mất tận 5000ms. Lỗi do Payment!
graph TD
    Gateway[API Gateway<br/>Generates TraceID] -->|Passes TraceID| Order[Order Service<br/>Span A]
    Order -->|Passes TraceID| Inventory[Inventory Service<br/>Span B]
    Order -->|Passes TraceID| Promo[Promo Service<br/>Span C]
    
    Gateway -.-> OTEL[Telemetry Collector]
    Order -.-> OTEL
    Inventory -.-> OTEL
    Promo -.-> OTEL
    
    OTEL --> ClickHouse[(ClickHouse<br/>Metrics & Log Storage)]
    OTEL --> Flink[Apache Flink<br/>Real-time Alerts]

2. Lưu trữ Logs cực độ với ClickHouse

Với hàng triệu request mỗi giây, việc sinh ra Spans và Logs sẽ tạo ra khối lượng dữ liệu khổng lồ (vài chục Terabytes mỗi ngày). Nếu dùng Elasticsearch (ELK Stack) truyền thống, máy chủ sẽ ngốn một lượng RAM khủng khiếp để duy trì các index Inverted.

Shopee đã chuyển hướng sang dùng ClickHouse - cơ sở dữ liệu OLAP dạng cột (Columnar Database) siêu tốc độ.

  • Tỉ lệ nén cực cao: Nhờ lưu trữ theo cột có chung kiểu dữ liệu, ClickHouse áp dụng các chuẩn nén như ZSTD, giảm không gian lưu trữ PetaBytes log đi gấp hàng chục lần so với Elastic.
  • Truy vấn Vectorized: Dù quét qua hàng tỉ dòng log, một kĩ sư chỉ mất 1-2 giây để chạy câu lệnh SELECT ... WHERE TraceID = 'a8f9x0' nhờ thuật toán quét dữ liệu vector hóa và kiến trúc xử lý song song đa lõi.

Log và Trace sinh ra không chỉ để cho con người đọc. Máy móc cũng đọc chúng. Shopee dùng Apache Flink - một framework Stream Processing - để xử lý chuỗi sự kiện chảy liên tục (Data stream) trong thời gian thực.

  • Cảnh báo lỗi tự động: Flink đếm số lượng lỗi 500 xuất hiện trên stream. Nếu vượt quá ngưỡng 100 lỗi/giây, nó bắn message qua Slack hoặc PagerDuty gọi kĩ sư dậy ngay lập tức.
  • Anti-Fraud (Chống gian lận): Nếu Flink phát hiện một IP spam tạo 1000 giỏ hàng trong 1 phút trên luồng Log, nó sẽ kích hoạt Rule block IP đó trước khi kẻ xấu kịp thực hiện giao dịch tiếp theo.

Bài học cho Dev: Hệ thống Microservices càng phức tạp thì càng bị “mù” nếu không xây dựng được hạ tầng Giám sát tốt. Bơm TraceID qua Headers, tập hợp Log tại một nơi như ClickHouse và trực quan hóa bằng Grafana là bước đầu tư bảo hiểm đáng giá nhất cho mọi dự án lớn.