Tracing là phương pháp quan sát luồng yêu cầu qua một hệ thống phân tán, trong đó mỗi bước xử lý được ghi lại như một sự kiện riêng biệt với dấu thời gian. Theo OpenTelemetry, 2025, một trace kết hợp đường dẫn đầy đủ của yêu cầu từ điểm vào đến phản hồi cuối cùng, đi qua tất cả các dịch vụ vi mô và lời gọi bên ngoài. Điều này cho phép các nhà phát triển xác định điểm nghẽn, độ trễ và lỗi trong các kiến trúc backend di động phức tạp.
Những điểm chính
Tracing là phương pháp quan sát phân tán trong đó mỗi yêu cầu đến được theo dõi qua tất cả dịch vụ và thành phần của hệ thống. Không giống như số liệu đo lường hiển thị giá trị tổng hợp (thời gian phản hồi trung bình, số lỗi), tracing giữ lại ngữ cảnh đầy đủ của một yêu cầu cụ thể.
Mỗi bước xử lý — lời gọi cơ sở dữ liệu, yêu cầu HTTP đến dịch vụ vi mô khác, thực thi tác vụ nền — được ghi lại như một đơn vị riêng biệt với dấu thời gian, trạng thái và thuộc tính. Theo Google Dapper (bài báo gốc năm 2010), tracing cho phép xác định vị trí độ trễ trong hệ thống phân tán với độ chính xác đến từng lời gọi.
Tracing đặc biệt quan trọng đối với ứng dụng di động nơi backend bao gồm hàng chục dịch vụ vi mô. Một thao tác người dùng — như đăng nhập tài khoản — có thể đi qua API Gateway, dịch vụ xác thực, cơ sở dữ liệu và dịch vụ Push. Nếu không có tracing, việc xác định thành phần nào làm chậm phản hồi là gần như không thể.
Đơn vị cơ bản của tracing là span. Mỗi span đại diện cho một thao tác logic: yêu cầu HTTP, truy vấn SQL, lời gọi gRPC, tuần tự hóa JSON. Một span chứa mã định danh duy nhất, mã định danh cha, tên thao tác, thời gian bắt đầu, thời lượng, trạng thái và một tập thuộc tính.
Tất cả span liên quan đến cùng một yêu cầu gốc được nhóm thành một trace. Span gốc đại diện cho điểm vào — yêu cầu HTTP từ ứng dụng di động đến API. Các span con tạo thành cây, trong đó mỗi span tham chiếu đến cha của nó qua trường parent_span_id.
Thời lượng của trace bằng tổng thời lượng của các đoạn thời gian duy nhất của tất cả span. Nếu hai span con thực thi song song, thời gian của chúng không được cộng dồn — điều này rất quan trọng để phân tích chính xác độ trễ do lời gọi song song tới các dịch vụ vi mô.
Mỗi span có thể chứa thuộc tính — cặp khóa-giá trị với thông tin meta: URL yêu cầu, ID người dùng, phiên bản API, tên máy chủ. Thuộc tính được dùng để lọc và nhóm các trace. Ngoài thuộc tính, span hỗ trợ sự kiện — dấu thời gian với mô tả văn bản, như "lỗi bộ nhớ đệm" hoặc "thử kết nối lại".
Distributed tracing giải quyết vấn đề liên kết các span được tạo trong các tiến trình khác nhau và trên các máy khác nhau. Cơ chế dựa trên truyền ngữ cảnh: khi dịch vụ A gọi dịch vụ B, một tiêu đề chứa ID trace hiện tại và ID span cha được thêm vào yêu cầu gửi đi.
Giao thức truyền ngữ cảnh tiêu chuẩn là W3C Trace Context (tiêu đề traceparent và tracestate) và Zipkin B3 (tiêu đề X-B3-TraceId, X-B3-SpanId). W3C Trace Context được W3C Consortium thông qua làm tiêu chuẩn vào năm 2021 và được tất cả nhà cung cấp dịch vụ đo xa chính hỗ trợ.
Khi nhận yêu cầu, dịch vụ B trích xuất trace_id từ tiêu đề và tạo span con với trace_id đó. Nhờ vậy, sau khi yêu cầu hoàn tất, tất cả span từ các dịch vụ khác nhau được kết hợp thành một trace duy nhất ở phía bộ thu thập. Điều này yêu cầu mỗi dịch vụ phải được trang bị cùng một thư viện tracing.
Trong phát triển di động, truyền ngữ cảnh bao gồm không chỉ backend mà còn tương tác máy khách-máy chủ. Ứng dụng di động có thể gửi trace_id trong tiêu đề của mỗi yêu cầu API, cho phép liên kết hành động của máy khách với xử lý phía máy chủ. SDK OpenTelemetry cho iOS và Android hỗ trợ tạo và truyền ngữ cảnh trace tự động qua máy khách HTTP.
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.context.Context
class TracingInterceptor : Interceptor {
private val tracer: Tracer = OpenTelemetry.getTracer("mobile-app")
override fun intercept(chain: Interceptor.Chain): Response {
val span = tracer.spanBuilder("HTTP POST /api/login")
.setParent(Context.current())
.startSpan()
return chain.proceed(chain.request())
.also { span.end() }
}
}
Bộ chặn Kotlin được trình bày tạo một span cho mỗi yêu cầu HTTP đến máy chủ. Ngữ cảnh cha được truyền từ mã gọi qua Context.current(), cho phép liên kết tracing phía máy khách với tracing phía máy chủ.
OpenTelemetry là tiêu chuẩn thực tế để thu thập dữ liệu trace. Nó cung cấp API thống nhất để tạo span, tự động trang bị công cụ cho các thư viện phổ biến và cơ chế linh hoạt để xuất dữ liệu đến nhiều hệ thống backend: Jaeger, Zipkin, Grafana Tempo, Datadog, New Relic.
OpenTelemetry hỗ trợ tạo span tự động cho các framework phổ biến: Spring Boot, Ktor, Flask, Express, gRPC. Nhà phát triển chỉ cần thêm một dependency vào dự án, thư viện sẽ tự động chặn các yêu cầu đến và đi. Tự động trang bị công cụ cho Java sử dụng javaagent để sửa đổi bytecode khi đang chạy mà không thay đổi mã nguồn.
Cho nền tảng di động, OpenTelemetry cung cấp Swift SDK và Kotlin SDK. Chúng tự động tạo span cho yêu cầu mạng (URLSession, OkHttp), thao tác cơ sở dữ liệu (CoreData, Room) và tác vụ nền. Nhà phát triển có thể thêm span tùy chỉnh cho logic nghiệp vụ.
Các span thu thập được gửi đến bộ thu thập qua giao thức OTLP (OpenTelemetry Protocol). Bộ thu thập có thể đệm, lọc và chuyển tiếp dữ liệu đến một hoặc nhiều hệ thống lưu trữ. Theo tài liệu OpenTelemetry, độ trễ điển hình từ khi tạo span đến khi hiển thị trên bảng điều khiển là 2–5 giây khi sử dụng xuất gRPC.
import OpenTelemetryApi
import OpenTelemetrySdk
import URLSessionInstrumentation
let instrumentation = URLSessionInstrumentation()
instrumentation.enable()
let tracer = OpenTelemetry.instance.tracerFactory
.get("mobile-monitoring")
let span = tracer.spanBuilder("fetch-user-profile")
.setAttribute(key: "user.id", value: userId)
.startSpan()
span.end()
Mã Swift kích hoạt tự động trang bị công cụ cho lớp mạng và tạo span tùy chỉnh cho thao tác lấy hồ sơ người dùng. Thuộc tính user.id cho phép lọc trace theo người dùng cụ thể sau này.
Trong hệ thống tải cao, không thể tracing mọi yêu cầu — điều này tạo ra tải không chấp nhận được cho lưu trữ và mạng. Lấy mẫu giải quyết vấn đề này bằng cách chỉ lưu một phần trace. Việc chọn chiến lược ảnh hưởng trực tiếp đến tính đầy đủ dữ liệu và chi phí hạ tầng.
Quyết định lưu trace được đưa ra tại thời điểm tạo — trong span gốc. Cách tiếp cận đơn giản và phổ biến nhất: tỷ lệ phần trăm cố định của yêu cầu (ví dụ 5%) được lưu, phần còn lại bị loại bỏ. Nhược điểm là không thể đảm bảo rằng các lỗi hiếm gặp sẽ được ghi lại. Probability sampler trong OpenTelemetry hỗ trợ cài đặt xác suất từ 0.0 đến 1.0.
Quyết định được hoãn lại cho đến khi tất cả span của trace hoàn tất. Một bộ phân tích đánh giá xem trace có chứa lỗi, vượt quá thời gian hoặc thuộc tính thú vị hay không, và chỉ khi đó mới lưu. Cách tiếp cận này yêu cầu đệm tất cả span trong bộ thu thập, làm tăng mức tiêu thụ bộ nhớ. Theo Grafana Labs, lấy mẫu tail-based hiệu quả hơn 40–60% về "chi phí trên mỗi dữ liệu hữu ích" trong các hệ thống có lỗi hiếm gặp nhưng nghiêm trọng.
| Chiến lược | Ưu điểm | Nhược điểm |
|---|---|---|
| Xác suất cố định | Đơn giản, tải dự đoán được | Bỏ lỡ sự kiện hiếm |
| Giới hạn tốc độ | Khối lượng dữ liệu đảm bảo | Phủ sóng không đồng đều |
| Tail-based | Ghi lại mọi lỗi | Tiêu thụ bộ nhớ cao |
| Thích ứng | Cân bằng chi phí và phủ sóng | Cấu hình phức tạp |
Ghi log ghi lại các sự kiện riêng lẻ với mức độ nghiêm trọng (info, warn, error) nhưng không liên kết chúng trong ngữ cảnh của một yêu cầu. Tracing, ngược lại, tạo ra một cây cấu trúc các thao tác thuộc về một yêu cầu đầu-cuối. Trong thực tế, hai cách tiếp cận này không loại trừ nhau mà bổ sung cho nhau.
Log hiệu quả cho phân tích chi tiết một lỗi cụ thể: nhà phát triển thấy thông báo chính xác, dấu vết ngăn xếp và giá trị biến. Tracing trả lời câu hỏi "tại sao yêu cầu mất 5 giây" — nó cho thấy dịch vụ vi mô hoặc lời gọi nào chiếm nhiều thời gian nhất. Theo Honeycomb (2024), các nhóm sử dụng tracing cùng với ghi log tìm ra nguyên nhân gốc rễ của sự cố nhanh hơn 2.3 lần.
Cách tiếp cận hiện đại — khả năng quan sát — kết hợp tracing, số liệu đo lường và log vào một hệ thống duy nhất. OpenTelemetry hỗ trợ tương quan giữa ba tín hiệu này: mỗi span có thể chứa liên kết đến log liên quan và số liệu đo lường có thể được gắn thẻ trace_id để đi sâu vào các trace cụ thể.
Câu hỏi thường gặp
Giám sát hiển thị các số liệu tổng hợp của hệ thống — thời gian phản hồi trung bình, số lỗi mỗi phút, tải CPU. Tracing hiển thị đường đi của một yêu cầu cụ thể qua tất cả thành phần. Giám sát trả lời "chuyện gì đang xảy ra", tracing trả lời "tại sao nó xảy ra".
Cho hệ thống sản xuất, 1–5% yêu cầu là đủ với lấy mẫu head-based. Nếu hệ thống hiếm khi tạo lỗi, nên dùng lấy mẫu tail-based tập trung vào ghi lại tất cả trace lỗi. Cho môi trường staging, có thể tracing 100% yêu cầu mà không giới hạn.
Các công cụ chính: Jaeger (giải pháp từ Uber, mã nguồn mở), Grafana Tempo (lưu trữ trace khả mở rộng), Datadog APM, New Relic Distributed Tracing, AWS X-Ray và Honeycomb. Tất cả đều hỗ trợ tiêu chuẩn OpenTelemetry cho việc tiếp nhận dữ liệu.
Có, tracing cục bộ hoạt động trong một tiến trình duy nhất. SDK OpenTelemetry cho iOS và Android tạo span cho các thao tác cục bộ: đọc cơ sở dữ liệu, xử lý ảnh, yêu cầu mạng. Các trace này không phân tán nhưng hữu ích để chẩn đoán hiệu suất phía máy khách.
Thư viện tracing hiện đại thêm dưới 1% chi phí với lấy mẫu head-based. OpenTelemetry sử dụng xuất dữ liệu bất đồng bộ không chặn luồng chính. Cho thiết bị di động, nên giới hạn tần suất tạo span và sử dụng chiến lược lấy mẫu thích ứng.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm