Elastic APM: ‘Nội soi’ mã nguồn và bắt bệnh hệ thống thay vì đoán mò

Monitoring tutorial - IT technology blog
Monitoring tutorial - IT technology blog

Tại sao Prometheus và Grafana là chưa đủ?

Hệ thống của mình từng chạy cụm Prometheus + Grafana để giám sát 15 server. Mọi thứ trông rất ổn cho đến một ngày user than phiền: “App load chậm như rùa”. Nhìn vào dashboard, CPU vẫn dưới 20%, RAM dư dả, mọi thông số đều hiện màu xanh mướt. Lúc này, mình mới nhận ra Prometheus chỉ cho biết hệ thống đang “sống”, chứ không thể trả lời câu hỏi: Tại sao một request cụ thể lại mất tới 10 giây để xử lý?

Vấn đề nằm ở đâu? Code xử lý chậm, query SQL thiếu index, hay API bên thứ ba đang bị timeout? Để giải quyết những bài toán “nội soi” sâu vào bên trong ứng dụng, chúng ta cần tới APM (Application Performance Monitoring).

Phân biệt các tầng giám sát

Nhiều anh em thường nhầm lẫn giữa log, metrics và tracing. Hãy phân biệt rõ để không dùng sai mục đích:

1. Giám sát qua Log (Logging)

Sử dụng ELK Stack hoặc Graylog để gom log tập trung. Phương pháp này hữu ích khi bạn đã biết lỗi xảy ra và cần tìm nguyên nhân chi tiết (stack trace). Tuy nhiên, dùng log để đo response time của 1 triệu request là điều bất khả thi.

2. Giám sát qua Metrics (Infrastructure Monitoring)

Chính là Prometheus. Nó tập trung vào sức khỏe phần cứng như CPU, RAM, Network. Nó báo cho bạn biết khi nào cần mua thêm server, nhưng hoàn toàn mù tịt về logic bên trong code.

3. Giám sát hiệu suất (APM – Tracing)

Các công cụ như New Relic, Datadog hay Elastic APM sẽ thực hiện instrumentation (gắn chip) vào code. Nó ghi lại hành trình của request từ lúc bắt đầu, đi qua các hàm, gọi vào database cho đến khi trả kết quả. Đây là chốt chặn cuối cùng để tối ưu trải nghiệm người dùng.

Lý do mình chọn Elastic APM

Sau khi dùng thử New Relic và thấy hóa đơn “phỏng tay” khi traffic tăng, mình đã chuyển hướng sang Elastic APM. Dưới đây là những trải nghiệm thực tế:

  • Điểm cộng: Tích hợp cực mượt nếu bạn đang dùng Elasticsearch làm log server. Nó hỗ trợ Distributed Tracing, cho phép theo dõi một request đi xuyên qua 5-7 microservices khác nhau. Bạn sẽ thấy rõ service nào đang là “kẻ tội đồ” gây chậm.
  • Điểm trừ: Dữ liệu tracing rất nặng. Nếu không cấu hình khéo, nó có thể ngốn hàng trăm GB ổ cứng mỗi ngày. Ngoài ra, Agent sẽ gây ra khoảng 1-3% overhead cho CPU, nhưng con số này hoàn toàn chấp nhận được so với giá trị nó mang lại.

Kiến trúc triển khai cơ bản

Mô hình này gồm 4 thành phần phối hợp nhịp nhàng:

  1. APM Agent: Thư viện nhúng vào code (Python, Node.js, Go…).
  2. APM Server: Trạm trung chuyển, nhận dữ liệu từ Agent để đẩy vào Elasticsearch.
  3. Elasticsearch: Kho lưu trữ khổng lồ chứa dữ liệu tracing.
  4. Kibana: Giao diện trực quan để anh em “soi” lỗi và xem biểu đồ.

Hướng dẫn triển khai thực tế

Chúng ta sẽ dựng nhanh hệ thống bằng Docker và tích hợp vào một ứng dụng Python để minh họa.

Bước 1: Khởi tạo cụm Elastic APM với Docker

Tạo file docker-compose.yml với cấu hình tối giản:

version: '3.8'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0
    environment:
      - discovery.type=single-node
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ports:
      - "9200:9200"

  kibana:
    image: docker.elastic.co/kibana/kibana:7.17.0
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch

  apm-server:
    image: docker.elastic.co/apm/apm-server:7.17.0
    ports:
      - "8200:8200"
    command: >
       apm-server -e
         -E apm-server.rum.enabled=true
         -E setup.kibana.host="kibana:5601"
         -E output.elasticsearch.hosts=["elasticsearch:9200"]
    depends_on:
      - elasticsearch
      - kibana

Chạy lệnh docker-compose up -d và đợi khoảng 1 phút để các service khởi động hoàn tất.

Bước 2: Gắn Agent vào ứng dụng Python

Cài đặt thư viện agent chính thức từ Elastic:

pip install elastic-apm

Với ứng dụng Flask, bạn chỉ cần thêm vài dòng cấu hình đơn giản:

from flask import Flask
from elasticapm.contrib.flask import ElasticAPM

app = Flask(__name__)
app.config['ELASTIC_APM'] = {
  'SERVICE_NAME': 'order-service',
  'SERVER_URL': 'http://localhost:8200',
  'ENVIRONMENT': 'production',
}

apm = ElasticAPM(app)

Khai thác dữ liệu trên Kibana

Khi có traffic đổ vào, hãy mở mục Observability > APM. Bạn sẽ thấy những con số biết nói:

1. Response Time (Latency)

Hãy chú ý vào chỉ số p95 và p99. Nếu p99 là 3 giây, nghĩa là 1% khách hàng của bạn đang trải nghiệm sự chậm trễ khó chấp nhận. Đây là căn cứ để team dev ưu tiên tối ưu endpoint nào trước.

2. Error Rate

APM thông minh hơn log ở chỗ nó tự động nhóm (group) các lỗi tương đồng. Thay vì nhìn 1.000 dòng log lỗi kết nối DB, bạn chỉ thấy một dòng duy nhất kèm biểu đồ tần suất xuất hiện.

3. Truy vết Database Queries

Đây là tính năng đáng giá nhất. Khi click vào một request chậm, Kibana hiển thị biểu đồ thác nước (waterfall). Bạn sẽ thấy câu query SELECT * FROM orders... mất bao nhiêu miligiây. Thực tế, team mình từng phát hiện một câu query thiếu index làm chậm toàn bộ hệ thống chỉ nhờ tính năng này.

Kinh nghiệm xương máu khi vận hành

Triển khai APM cho hệ thống thực tế cần lưu ý 3 điểm mấu chốt:

  • Sampling Rate: Với hệ thống có 10.000 request/giây, đừng bao giờ log 100%. Hãy chỉnh transaction_sample_rate về mức 0.05 (lấy mẫu 5%). Điều này giúp giảm tải cho Elasticsearch mà vẫn đảm bảo tính thống kê.
  • Bảo mật: Luôn cấu hình secret_token cho APM Server. Nếu không, bất kỳ ai cũng có thể gửi dữ liệu rác làm tràn ngập ổ cứng của bạn.
  • Alerting: Đừng đợi đến khi check dashboard. Hãy thiết lập cảnh báo qua Telegram khi Error Rate vượt ngưỡng 2% trong vòng 5 phút liên tục.

Làm chủ Elastic APM không chỉ là cài đặt công cụ, mà là xây dựng văn hóa tối ưu dựa trên dữ liệu. Sau 3 tháng áp dụng, team mình đã giảm được 40% thời gian phản hồi trung bình và loại bỏ hoàn toàn các lỗi “chậm không rõ nguyên nhân”.

Share: