Distributed Tracing
Monolitik bir uygulamada bir hata oluştuğunda, tek bir log dosyasına bakarak sorunu bulabilirsiniz. Ancak mikroservis mimarisinde bir istek düzinelerce servisten geçebilir. Hangi serviste hata oluştuğunu, darboğazın nerede olduğunu anlamak için distributed tracing (dağıtık izleme) gereklidir. Bu derste trace ve span kavramlarını, Micrometer Tracing'i, Zipkin entegrasyonunu ve correlation ID propagation'ı öğreneceğiz.
Trace ve Span Kavramları
Trace: Bir isteğin sistemdeki tüm yolculuğunu temsil eden uçtan uca iz. Her trace benzersiz bir traceId'ye sahiptir.
Span: Bir trace içindeki tek bir operasyonu temsil eder. Her span'in kendi spanId'si, başlangıç zamanı ve süresi vardır. Span'ler parent-child ilişkisine sahiptir:
TraceId: abc123
├── Span A: Gateway (root span) [0ms-250ms]
│ ├── Span B: Order Service [10ms-200ms]
│ │ ├── Span C: User Service [20ms-80ms]
│ │ └── Span D: Product Service [90ms-150ms]
│ └── Span E: Payment Service [210ms-240ms]Tüm span'ler aynı traceId'yi paylaşır. Bu sayede bir isteğin tüm servisler arasındaki yolculuğu tek bir trace altında birleştirilir.
Micrometer Tracing Kurulumu
Spring Cloud Sleuth'un yerini alan Micrometer Tracing:
<!-- Micrometer Tracing Bridge -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<!-- Zipkin Reporter -->
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>application.yml:
management:
tracing:
sampling:
probability: 1.0 # %100 örnekleme (prod'da 0.1 = %10)
zipkin:
tracing:
endpoint: http://localhost:9411/api/v2/spans
logging:
pattern:
level: "%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]"Bu konfigürasyon ile log çıktıları otomatik olarak traceId ve spanId içerir:
INFO [order-service,abc123def456,789xyz] Processing order #42
INFO [order-service,abc123def456,aaa111] Calling user-serviceCorrelation ID (İlişkilendirme Kimliği)
Correlation ID, bir isteğe atanan benzersiz kimlik numarasıdır ve isteğin tüm servisler arasındaki yolculuğunu izlemek için kullanılır. Micrometer Tracing'in traceId'si aslında bir correlation ID'dir:
// İstek geldiğinde traceId otomatik oluşturulur
// Her servis çağrısında HTTP header ile propagate edilir:
// traceparent: 00-abc123def456-789xyz-01Trace Propagation (İz Yayılımı)
Trace bilgisi servisler arasında HTTP header'ları ile yayılır. W3C Trace Context standardı kullanılır:
# W3C Trace Context header
traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
# version-traceId-parentSpanId-flagsSpring Boot bunu otomatik olarak yönetir. RestTemplate, WebClient ve Feign Client üzerinden yapılan çağrılarda trace header'ları otomatik eklenir ve alınır:
// Order Service → User Service çağrısı
// Micrometer otomatik olarak traceparent header'ını ekler
UserDto user = restTemplate.getForObject(
"http://user-service/api/users/{id}",
UserDto.class, userId);
// Header: traceparent: 00-abc123-span456-01 → otomatik eklendiZipkin
Zipkin, trace verilerini toplamak, depolamak ve görselleştirmek için kullanılan açık kaynak bir platformdur:
# Docker ile Zipkin başlatma
docker run -d -p 9411:9411 openzipkin/zipkinZipkin Dashboard (http://localhost:9411) üzerinde:
Trace listesi — Tüm trace'leri zaman damgası, süre ve servis adıyla listeler.
Trace detayı — Bir trace'in tüm span'lerini waterfall (şelale) grafiğinde gösterir.
Dependency grafiği — Servislerin birbirleriyle iletişim haritasını çizer.
Özel Span Oluşturma
Otomatik span'lere ek olarak, kendi span'lerinizi oluşturabilirsiniz:
@Service
public class OrderService {
private final Tracer tracer;
public OrderService(Tracer tracer) {
this.tracer = tracer;
}
public Order processOrder(OrderRequest request) {
// Özel span başlat
Span inventorySpan = tracer.nextSpan()
.name("check-inventory")
.tag("product.id", request.getProductId().toString())
.start();
try (Tracer.SpanInScope ws =
tracer.withSpan(inventorySpan)) {
// Envanter kontrolü
boolean available = inventoryService.check(
request.getProductId(), request.getQuantity());
inventorySpan.tag("inventory.available",
String.valueOf(available));
if (!available) {
inventorySpan.tag("error", "out of stock");
throw new OutOfStockException();
}
return createOrder(request);
} finally {
inventorySpan.end();
}
}
}@Observed Annotation
Spring Boot 3'te Micrometer Observation API ile daha temiz span oluşturma:
@Service
public class PaymentService {
@Observed(name = "payment.process",
contextualName = "process-payment",
lowCardinalityKeyValues = {"payment.type", "credit-card"})
public PaymentResult processPayment(PaymentRequest request) {
// Bu metot otomatik olarak bir span oluşturur
// Süre, başarı/hata durumu otomatik kaydedilir
return gateway.charge(request);
}
}Distributed tracing, mikroservis mimarisinde observability'nin temel direğidir. Production'da sampling oranını %10-20'de tutun, trace tag'lerine hassas bilgi eklemeyin ve Elasticsearch backend ile uzun süreli saklama yapın.
AI Asistan
Sorularını yanıtlamaya hazır