Gymterview
middle

Как организовать распределённую трассировку в микросервисах?

Distributed Tracing (распределённая трассировка) — это метод отслеживания прохождения запроса через цепочку микросервисов, позволяющий понять, какие сервисы были вызваны, сколько времени занял каждый вызов и где произошла ошибка.

Основные понятия

  • Trace — полный путь запроса через все сервисы (от входа до ответа).
  • Span — одна операция в рамках trace (например, вызов одного сервиса или запрос к БД).
  • Trace ID — уникальный идентификатор всего запроса (передаётся между сервисами).
  • Span ID — идентификатор конкретной операции.
  • Parent Span ID — ссылка на родительский span (для построения дерева вызовов).
Пример
Trace ID: abc123
├── Span 1: API Gateway (50ms)
│   ├── Span 2: Payment Service (30ms)
│   │   ├── Span 3: DB Query (5ms)
│   │   └── Span 4: Customer Service call (20ms)
│   │       └── Span 5: DB Query (3ms)
│   └── Span 6: Notification Service (10ms)
Micrometer Tracing + Zipkin (Spring Boot 3+)
<!-- pom.xml -->
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
    <groupId>io.zipkin.reporter2</groupId>
    <artifactId>zipkin-reporter-brave</artifactId>
</dependency>
# application.yml
management:
  tracing:
    sampling:
      probability: 1.0  # 100% запросов трассируются (в prod обычно 0.1)
  zipkin:
    tracing:
      endpoint: http://zipkin:9411/api/v2/spans

logging:
  pattern:
    level: "%5p [${spring.application.name},%X{traceId},%X{spanId}]"

Trace ID и Span ID автоматически прокидываются в логи:

INFO [payment-service,abc123def456,span789012] Processing payment #42
INFO [customer-service,abc123def456,span345678] Fetching customer data
Создание кастомных span
@Service
@RequiredArgsConstructor
public class PaymentService {
    private final ObservationRegistry observationRegistry;

    public void processPayment(PaymentRequest request) {
        Observation.createNotStarted("payment.processing", observationRegistry)
            .lowCardinalityKeyValue("payment.type", request.getType().name())
            .observe(() -> {
                // Этот блок будет отдельным span
                validatePayment(request);
                executePayment(request);
            });
    }
}

Инструменты визуализации

  • Zipkin — простой и легковесный, хорошо интегрируется со Spring.
  • Jaeger — более мощный, поддерживает сэмплирование, создан Uber.
  • Grafana Tempo — интеграция с Grafana, поддержка больших объёмов.

На собеседовании: объясните понятия Trace и Span, покажите, что знаете Micrometer Tracing как замену Spring Cloud Sleuth (устарел в Spring Boot 3). Частая ошибка — не упомянуть sampling в production (100% трассировка создаёт огромную нагрузку).