Sau bài này bạn làm được: định nghĩa và đo RED metric cho một HTTP service; đọc access log NGINX và trích xuất p99 latency; truyền trace ID qua service boundary và tìm nó trong log.
Tại sao cần observability cho mạng
Hạ tầng mạng “chạy ổn” không có nghĩa là “chạy tốt”. Không có observability, bạn chỉ biết hệ thống bị lỗi sau khi user báo, và mất rất nhiều thời gian tìm nguyên nhân.
Không có observability:
User: "App bị chậm"
Bạn: tail log → thấy gì? grep lỗi → khoảng thời gian nào? → mất 30 phút
Có observability:
Alert: p99 latency > 2s trong 5 phút
Dashboard: tăng 13:42 → correlate với deploy → rollback ngay
RED và USE — hai framework metric
RED (cho service hướng request)
| Chữ | Metric | Ví dụ |
|---|---|---|
| Rate | Request/s | rate(http_requests_total[5m]) |
| Errors | Error rate | rate(http_requests_total{code=~"5.."}[5m]) |
| Duration | Latency distribution | p50, p95, p99 của response time |
Dùng cho: HTTP API, gRPC service, bất kỳ service có request/response.
USE (cho tài nguyên)
| Chữ | Metric | Ví dụ |
|---|---|---|
| Utilization | % capacity đang dùng | CPU 80%, connection pool 90% |
| Saturation | Queue / backlog | TCP backlog, request queue depth |
| Errors | Lỗi hard | NIC error, packet drop |
Dùng cho: CPU, memory, network interface, DB connection pool.
Access log — nguồn dữ liệu rẻ nhất
NGINX access log chứa đủ thông tin để tính RED metric:
# nginx.conf - log format với thời gian
log_format main '$remote_addr - $request_time $status '
'"$request" $body_bytes_sent '
'"$http_x_forwarded_for" "$http_user_agent"';
Phân tích nhanh với awk:
# p99 latency từ access log (sort + percentile thủ công)
awk '{print $3}' /var/log/nginx/access.log \
| sort -n | awk 'BEGIN{c=0} {a[c++]=$1} END{print a[int(c*0.99)]}'
# Đếm HTTP status code
awk '{print $4}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# Top 10 path chậm nhất (>2s)
awk '$3 > 2 {print $3, $5}' /var/log/nginx/access.log | sort -rn | head -10
Với Prometheus + NGINX:
# nginx-prometheus-exporter hoặc OpenTelemetry collector đọc log
# → Grafana dashboard tự động
Trace ID — theo dõi request qua nhiều service
Khi request đi qua nhiều service, cần một trace ID duy nhất để ghép log lại:
[Client] ──▶ [API Gateway] ──▶ [Service A] ──▶ [Service B]
X-Trace-ID: abc123 abc123 abc123
Log từng service đều chứa abc123 → grep một ID tìm ra toàn bộ chuỗi
Truyền trace ID trong HTTP header:
X-Request-ID: abc123 # tự định nghĩa
X-B3-TraceId: ... # Zipkin/B3 format
traceparent: 00-abc123... # W3C Trace Context (chuẩn mới, khuyến nghị)
Trong app (Node.js ví dụ):
// Middleware: gán trace ID
app.use((req, res, next) => {
req.traceId = req.headers["x-request-id"] || crypto.randomUUID();
res.setHeader("X-Request-ID", req.traceId);
next();
});
// Khi gọi service khác, truyền trace ID
fetch("http://service-b/api", {
headers: { "X-Request-ID": req.traceId },
});
// Log với trace ID
logger.info({ traceId: req.traceId, path: req.path }, "request received");
Metric mạng quan trọng cần theo dõi
Tại tầng LB / Ingress
# Prometheus queries ví dụ (NGINX Ingress Controller)
# Request rate
rate(nginx_ingress_controller_requests[5m])
# Error rate (5xx)
rate(nginx_ingress_controller_requests{status=~"5.."}[5m])
/ rate(nginx_ingress_controller_requests[5m])
# p99 latency
histogram_quantile(0.99,
rate(nginx_ingress_controller_request_duration_seconds_bucket[5m]))
# Active connections
nginx_ingress_controller_nginx_process_connections{state="active"}
Tại tầng TCP (Linux host)
# Connection state hiện tại
ss -tan | awk '{print $1}' | sort | uniq -c
# Chi tiết TCP info của từng socket: RTT, retransmit, cwnd, rcv_space
ss -tip state established
# Drop packet trên NIC
ip -s link show eth0 | grep -A2 "RX\|TX"
# TCP retransmit, syncookies, listen overflow… (nstat thay cho netstat -s)
nstat -az | grep -E "Retrans|Listen|SyncookiesSent|TcpExtTCPSynRetrans"
# Hoặc đọc trực tiếp counter tăng dần:
cat /proc/net/snmp | grep Tcp
ss -ti cho phép nhìn trạng thái sức khoẻ từng kết nối: rtt:1.2/0.5ms cwnd:10 bytes_acked:... retrans:0/3 — cực hữu ích khi nghi ngờ packet loss với một đối tác cụ thể. nstat -az là công cụ khuyến nghị thay netstat -s (đã deprecated trên nhiều distro).
eBPF observability (xu hướng 2025)
Với kernel ≥ 4.15, các công cụ eBPF cho phép quan sát traffic không cần sidecar, không sửa app:
- Cilium Hubble: flow log L3/L4/L7 trên K8s — theo dõi HTTP method, gRPC service, DNS query của mọi Pod.
- Pixie (CNCF, New Relic): capture request/response ở kernel, auto-tracing gRPC, Redis, MySQL.
- bpftrace / bcc: scripting cho investigation ad-hoc (
tcplife,tcpretrans,tcpconnect).
Khác với packet capture (tcpdump): eBPF đọc metadata ở chỗ kernel đã decode, gần như zero overhead và không bỏ sót gói ở mạng tốc độ cao.
Backlog — dấu hiệu overload
Accept backlog là hàng chờ connection TCP đã hoàn thành handshake nhưng chưa được app accept():
ss -lntp
# State Recv-Q Send-Q Local Addr:Port
# LISTEN 150 128 0.0.0.0:80
# Recv-Q > 0 trên LISTEN socket → backlog đang đầy!
# 150 > 128 (somaxconn) → kernel bắt đầu DROP SYN mới
Khi backlog đầy → client thấy timeout (không phải refused).
Alert nên có: Recv-Q trên LISTEN socket > 0 trong > 30s.
Dashboard tối thiểu
Một dashboard mạng cơ bản nên có:
- Rate: request/s theo service và endpoint.
- Error rate: % 5xx, % 4xx.
- Latency: p50, p95, p99 — theo thời gian.
- Active connections: đang ESTABLISHED.
- LB health: số instance healthy/unhealthy.
Thêm khi có: packet drop, TCP retransmit, connection pool saturation.
Tóm tắt
- RED cho service request; USE cho tài nguyên — hai framework bổ sung nhau.
- Access log là nguồn dữ liệu không cần instrumentation — phân tích ngay từ log.
- Trace ID trong header là điều kiện tối thiểu để debug request qua nhiều service.
- Backlog đầy = client timeout, không phải refused — theo dõi
Recv-Q.
Câu hỏi hay gặp
p99 tăng mạnh sau deploy nhưng p50 vẫn thấp — gợi ý gì?
Trả lời: Thường là một nhánh request hoặc một tỷ lệ nhỏ chậm (cold start, lock, query xấu, canary). Cần histogram/percentile theo route, so sánh phiên bản và trace vài request chậm.
Không có trace ID — lọc log thế nào? Có trace ID thì lợi gì?
Trả lời: Không có trace: lọc theo thời gian + path + status + IP — mất thời gian. Có trace ID: grep một ID xuyên gateway → app → downstream — nhanh và chắc.
USE: metric nào “báo trước” overload?
Trả lời: Saturation (queue backlog, connection pool đầy, Recv-Q tăng, CPU run queue) thường sớm hơn error rate — utilization 100% đã muộn hơn một bước.
Bài tiếp theo (Giai đoạn IV): IaC và GitOps cho hạ tầng mạng — quản lý Security Group, route và listener bằng code, không click-ops.