Khi xem qua đoạn code cấu hình OpenTelemetry, tớ nhận thấy team đang sử dụng SimpleSpanProcessor
:
OpenTelemetryModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => {
const serviceName = configService.get('SERVICE_NAME');
return {
serviceName,
spanProcessor: new SimpleSpanProcessor(
new OTLPTraceExporter({
url: configService.get('OPEN_TELEMETRY_TRACE_URL'),
}),
)
};
},
inject: [ConfigService],
}),
Thoạt nhìn, đoạn code trên hoàn toàn bình thường và đúng chuẩn. Nhưng vì tính tò mò nên tớ quyết định tìm hiểu thêm về OpenTelemetry và xem liệu có gì có thể cải thiện không.
Sau một hồi đọc tài liệu, tớ phát hiện ra OpenTelemetry cung cấp hai loại SpanProcessor chính:
Tài liệu còn nhấn mạnh rằng:
“BatchSpanProcessor được khuyến nghị sử dụng trong môi trường production vì nó hiệu quả hơn về tài nguyên. SimpleSpanProcessor nên chỉ được sử dụng trong môi trường phát triển hoặc debug.”
Nhưng tớ vẫn chưa biết dùng BatchSpanProcessor, theo lý thuyết có vẻ hay đó, nhưng test lại xem sao há 😆
Với thông tin này, tớ đặt giả thuyết: “Nếu chuyển từ SimpleSpanProcessor sang BatchSpanProcessor, hiệu suất hệ thống sẽ cải thiện đáng kể.”
Để kiểm chứng, tớ quyết định dùng k6 – một công cụ load testing mạnh mẽ, để so sánh hiệu suất giữa hai cấu hình.
Khi chạy ứng dụng với SimpleSpanProcessor, Grafana hiển thị mức tải CPU rất cao:
Tớ thay đổi cấu hình thành:
OpenTelemetryModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => {
const serviceName = configService.get('SERVICE_NAME');
return {
serviceName,
spanProcessor: new BatchSpanProcessor(
new OTLPTraceExporter({
url: configService.get('OPEN_TELEMETRY_TRACE_URL'),
}),
{
maxQueueSize: 4096,
scheduledDelayMillis: 500,
maxExportBatchSize: 512,
},
)
};
},
inject: [ConfigService],
}),
Biểu đồ CPU Usage: Đường màu xanh (trái) là SimpleSpanProcessor, đường màu cam và vàng (phải) là BatchSpanProcessor
Quả thật sử dụng BatchSpanProcessor đã cải thiện đáng kể hiệu suất CPU(phần này mình quên check RAM và Network @@)
Để dễ hiểu sự khác biệt, có thể tưởng tượng như thế này:
Request 1 → Tạo Span → Gửi Span → Tiếp tục xử lý
Request 2 → Tạo Span → Gửi Span → Tiếp tục xử lý
Request 3 → Tạo Span → Gửi Span → Tiếp tục xử lý
...
Request 1 → Tạo Span → Lưu vào buffer → Tiếp tục xử lý
Request 2 → Tạo Span → Lưu vào buffer → Tiếp tục xử lý
Request 3 → Tạo Span → Lưu vào buffer → Tiếp tục xử lý
...
(Sau 500ms hoặc khi đủ 512 spans)
→ Gửi tất cả spans trong một request
Xem qua 2 cách hoạt động dễ dàng thấy được BatchSpanProcessor hoạt động một cách tối ưu hơn, không phải gửi liên tục Span, nhưng khi sử dụng BatchSpanProcessor bạn cần hiểu rõ các thông số cấu hình để hệ thống hoạt động trơn tru hơn
Trong cấu hình của BatchSpanProcessor, tớ đã thiết lập 3 tham số quan trọng:
Các thông số này tuỳ thuộc vào hệ thống của bạn mà cân nhắc tuỳ chỉnh cho phù hợp nha
Nguon: viblo
You need to login in order to like this post: click here
YOU MIGHT ALSO LIKE