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

«Как организовать сквозное отслеживание запросов между микросервисами?» — вопрос из категории Архитектура, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Сквозное отслеживание (distributed tracing) в микросервисной архитектуре реализуется путем генерации и передачи уникального идентификатора запроса (Trace ID или Correlation ID) через все сервисы, которые участвуют в его обработке.

Основные подходы

  1. Передача через HTTP-заголовки

    Это самый распространенный способ для синхронных взаимодействий. На входе в систему (например, в API Gateway) генерируется уникальный ID, который затем добавляется в HTTP-заголовки всех последующих запросов к другим сервисам.

    • Стандартные заголовки: X-Request-ID, X-Correlation-ID.
    • W3C Trace Context: современный стандарт, использующий заголовки traceparent и tracestate.
    # Сервис А (вызывает Сервис Б)
    import requests
    import uuid
    
    # Получаем trace_id из входящего запроса или генерируем новый
    trace_id = request.headers.get('X-Request-ID', str(uuid.uuid4()))
    
    headers = {'X-Request-ID': trace_id}
    response = requests.get('http://service-b/data', headers=headers)
  2. Использование контекста в логах

    Trace ID должен быть включен во все записи логов, относящиеся к данному запросу. В Python для этого идеально подходит contextvars, который безопасно работает в асинхронном коде (в отличие от threading.local).

    # middleware.py
    import logging
    from contextvars import ContextVar
    
    # Глобальная контекстная переменная
    trace_id_var = ContextVar('trace_id', default=None)
    
    # Фильтр для логгера, который добавляет trace_id в запись
    class TraceIdFilter(logging.Filter):
        def filter(self, record):
            record.trace_id = trace_id_var.get()
            return True
  3. Инструменты и стандарты

    Вместо ручной реализации лучше использовать готовые решения, которые автоматизируют сбор и визуализацию трейсов:

    • OpenTelemetry (OTel): текущий индустриальный стандарт для инструментирования кода. Он предоставляет API и SDK для сбора телеметрии (трейсов, метрик, логов).
    • Jaeger, Zipkin: популярные open-source системы для сбора, хранения и визуализации распределенных трейсов. Они принимают данные от приложений, инструментированных с помощью OpenTelemetry.

Ключевые принципы

  • Генерация: Trace ID создается на самой границе системы (API Gateway, Load Balancer).
  • Пропагация: ID передается через все слои: HTTP-запросы, gRPC вызовы, сообщения в очередях (например, в метаданных Kafka/RabbitMQ).
  • Агрегация: Все логи и трейсы с одним и тем же ID собираются в централизованной системе (например, ELK Stack, Jaeger) для анализа.