도입
서비스가 여러 개로 분리되면 요청 하나의 흐름을 추적하기 어려워진다.
로그만으로는 어디서 느려졌는지, 어디서 실패했는지 파악이 힘들다.
이 문제를 해결하는 방식이 Distributed Tracing이다.
핵심 개념 설명
Distributed Tracing은 하나의 요청을 여러 서비스에 걸쳐 추적하는 기술이다.
핵심은 trace_id다. 요청 전체를 하나로 묶는 식별자다.
- trace_id: 전체 요청 식별
- span: 각 서비스 작업 단위
- trace: 여러 span의 집합
결국 요청 하나를 끝까지 따라가는 구조다. 서비스가 나뉘어도 흐름이 끊기지 않는다.
동작 원리 또는 구조
요청이 시작되면 trace_id가 생성된다. 이 값이 모든 서비스로 전달된다.
각 서비스는 span을 생성한다. 그리고 같은 trace_id로 연결된다.
이 데이터는 하나의 타임라인으로 묶인다. 문제 지점을 시각적으로 확인할 수 있다.
실무 기준 / 적용 방법
1. trace_id 생성
요청 시작 지점에서 생성한다. 보통 API Gateway나 첫 서버다.
이 값은 절대 바뀌면 안 된다. 끝까지 동일하게 유지해야 한다.
<?php
$traceId = bin2hex(random_bytes(8));
$request->headers->set('X-Trace-Id', $traceId);
2. 서비스 간 전달
trace_id는 반드시 헤더로 전달한다. 이걸 놓치면 흐름이 끊긴다.
<?php
$client->post('http://service-b/api', [
'headers' => [
'X-Trace-Id' => $traceId
]
]);
특히 내부 API 호출과 큐 처리에서 자주 빠지는 부분이다.
3. 로그와 함께 사용
Tracing만으로는 부족하다. 로그에도 trace_id를 반드시 포함해야 한다.
그래야 로그 검색과 연결된다. 실제 운영에서는 이게 핵심이다.
<?php
logger()->info('payment_start', [
'trace_id' => $traceId,
'order_id' => $orderId
]);
logger()->error('payment_failed', [
'trace_id' => $traceId,
'reason' => $error
]);
4. OpenTelemetry 적용
현재 표준은 OpenTelemetry다. 자동으로 span 생성과 전송을 처리한다.
수집된 데이터는 Jaeger나 Zipkin으로 보낸다. 웹 UI에서 흐름을 확인할 수 있다.
# Jaeger 실행
docker run -d \
-p 16686:16686 \
-p 6831:6831/udp \
jaegertracing/all-in-one
자주 발생하는 문제
1. trace_id 전달 누락
서비스 호출 시 헤더를 빼먹으면 다른 trace로 분리된다.
이 경우 전체 흐름이 끊긴다. 가장 흔한 실수다.
2. 로그와 분리됨
trace는 있는데 로그에 trace_id가 없으면 문제 분석이 어렵다.
두 시스템은 반드시 연결해야 한다. trace_id가 공통 키다.
3. span 과다 생성
span이 너무 많으면 오히려 읽기 어려워진다.
핵심 흐름만 남겨야 한다. 보여줄 수 있어야 의미가 있다.
4. 성능 오버헤드
모든 요청을 수집하면 부담이 된다. 특히 트래픽이 많을수록 영향이 크다.
샘플링 전략을 적용해야 한다. 예: 10%만 수집
한 줄 요약
Distributed Tracing은 trace_id를 기반으로 요청 흐름을 끝까지 연결해 추적하는 기술이며, 실무에서는 로그와 함께 사용해야 의미가 있다.
댓글 0