+3

BÀI 7: ADVANCED APM – DISTRIBUTED TRACING TRONG KIẾN TRÚC MICROSERVICES

Chào các bạn! Chào mừng các bạn đã đi đến bài viết cuối cùng trong series "Làm Chủ Elastic APM Từ Số 0". Ở bài trước, chúng ta đã biết cách dùng APM để tối ưu một ứng dụng đơn lẻ (Monolithic).

Thế nhưng ngày nay, các hệ thống lớn thường được bẻ nhỏ thành kiến trúc Microservices. Khi một User bấm nút "Thanh toán", Request sẽ đi qua API Gateway, nhảy sang Service Đơn hàng (Order), gọi tiếp sang Service Ví điện tử (Payment), rồi lại kích hoạt Service Kho hàng (Warehouse)...

Nếu hệ thống bỗng nhiên phản hồi chậm, làm sao bạn biết nó đang bị nghẽn ở Service nào? Làm sao kết nối các logs rời rạc của từng Service lại với nhau?

Câu trả lời chính là Distributed Tracing (Vết dấu phân tán) – tính năng tối cao của Elastic APM mà chúng ta sẽ cùng làm chủ hôm nay.

1. Bài toán: Request "bặt vô âm tín" giữa các Service

Trong kiến trúc Microservices, mỗi Service thường chạy trên một cụm Container riêng, sử dụng database riêng và thậm chí viết bằng các ngôn ngữ khác nhau (Service A viết bằng Laravel, Service B viết bằng Golang).

Khi không có APM, nếu Service Payment bị chậm, toàn bộ các Service gọi nó cũng sẽ bị chậm dây chuyền theo kiểu Domino. Logs của Service Order chỉ ghi vỏn vẹn: Gateway Timeout. Bạn sẽ phải nhảy qua logs của từng Service để "đoán mò".

Distributed Tracing giải quyết triệt để vấn đề này bằng cách liên kết toàn bộ hành trình của Request xuyên suốt qua tất cả các Service, vẽ thành một biểu đồ thác nước duy nhất trên Kibana.

2. Bí mật nằm ở đâu? W3C Trace Context

Làm sao Elastic APM Agent ở Service B (viết bằng Go) biết được Request này được gửi tới từ Service A (viết bằng Laravel)?

Bí mật nằm ở việc "Truyền tín hiệu qua HTTP Header" theo tiêu chuẩn W3C Trace Context.

Khi Service A chuẩn bị gọi một HTTP Request sang Service B, APM Agent ở Service A sẽ tự động "lén" tiêm (inject) một đoạn mã định danh vào HTTP Header của Request đó có tên là traceparent.

Đoạn Header traceparent sẽ có định dạng dạng như sau:

versiontrace_idparent_idtrace_flags\text{version} - \text{trace\_id} - \text{parent\_id} - \text{trace\_flags}

Ví dụ thực tế: traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01

  • 4bf92f3577b34da6a3ce929d0e0e4736: Chính là Trace ID gốc của toàn bộ hành trình (như chúng ta đã học ở Bài 3).
  • 00f067aa0ba902b7: Là Parent ID (Chính là Span ID của đoạn code vừa gọi HTTP ở Service A).

Khi Service B nhận được Request, APM Agent của Service B sẽ "đọc" cái Header này ra, lấy luôn cái trace\_id đó để làm việc tiếp. Nhờ vậy, chuỗi hành trình không bao giờ bị đứt đoạn!

3. Bản đồ vạn hoa: Service Map trên Kibana

Khi Distributed Tracing hoạt động mượt mà, Elastic APM sẽ tặng bạn một món quà cực kỳ vô giá trên giao diện Kibana: Service Map.

Kibana sẽ tự động vẽ ra một sơ đồ mạng lưới hiển thị trực quan cấu trúc hệ thống của bạn:

  • Điểm tròn nào to, có màu Đỏ/Vàng nghĩa là Service đó đang có tỷ lệ lỗi cao hoặc đang bị quá tải (High Latency).
  • Đường mũi tên kết nối giữa các Service sẽ hiển thị tần suất gọi và tốc độ phản hồi.

Chỉ cần nhìn vào Service Map, đội ngũ SRE hay Developer có thể khoanh vùng ngay lập tức tâm dịch của sự cố mà không cần tốn một câu hỏi han lẫn nhau.

TỔNG KẾT SERIES: HÀNH TRÌNH LÀM CHỦ ELASTIC APM

Vậy là chúng ta đã cùng nhau đi qua trọn vẹn 7 bài học của Series: từ việc hiểu Tư duy giám sát hiện đại (Bài 1), nắm vững Kiến trúc và Ngôn ngữ APM (Bài 2, 3), tự tay Dựng hạ tầng bằng Docker (Bài 4), Tích hợp mã nguồn (Bài 5), Tối ưu hóa hệ thống (Bài 6), cho đến Giám sát Microservices nâng cao (Bài 7).

APM không đơn thuần là một công cụ Setup cho vui, nó là một Tư duy vận hành. Một kỹ sư backend giỏi không chỉ là người viết ra code chạy được, mà phải là người biết code của mình đang chạy như thế nào khi đối mặt với hàng triệu traffic thực tế.

Hi vọng series này mang lại những kiến thức thực chiến bổ ích cho công việc hằng ngày của các bạn.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí