B2B Engineering Insights & Architectural Teardowns

Трейсинг в actor-модели без деградации через Envelope

В actor-системах нет встроенного канала для trace context. Discord решил это без смены архитектуры и без остановки продакшена.

Проблема проявляется на границе модели. В HTTP trace context передаётся в заголовках. В Elixir actor-системе сообщения — произвольные структуры без метаданных. Стандартный OpenTelemetry работает внутри сервиса, но теряет связность между процессами. На масштабе Discord это означает слепые зоны: миллионы конкурентных пользователей, fanout на тысячи получателей и отсутствие end-to-end трассировки. При попытке добавить трейсинг наивно система упирается в CPU и объём данных.

Решение — не ломать модель, а обернуть её. Команда ввела примитив Envelope: сообщение + сериализованный trace context. Библиотека Transport подменяет вызовы GenServer (call/cast) и автоматически добавляет контекст. На приёмнике единая точка нормализации обрабатывает как «старые» сообщения, так и новые с Envelope. Это ключевой компромисс: минимальное вторжение в код против необходимости поддерживать двойной формат на период миграции. Взамен — возможность катить изменения без рестартов и синхронных апдейтов кластера.

Имплементация уткнулась в два узких места: fanout и стоимость (de)serialization. При рассылке в гильдии с тысячами получателей один запрос порождает лавину span’ов. Команда ввела динамический sampling по размеру fanout: 100% для одиночных сообщений, 10% при ~100 получателях, 0.1% при 10k+. Далее — агрессивная экономия CPU:

  • Контекст передаётся только для сэмплированных операций. Несэмплированные сообщения идут без trace context.
  • Сервис сессий не инициирует новые трейсы на fanout, а лишь продолжает существующие. Это снизило загрузку CPU примерно с 55% до 45%.
  • В gRPC-связке с Python 75% времени уходило на распаковку контекста. Добавлен быстрый фильтр: чтение флага sampling без полной десериализации и отказ от передачи контекста, если он не нужен.

Результат — наблюдаемость (Observability), которая масштабируется вместе с нагрузкой. Трейсы стали пригодны для реальных инцидентов: например, выявлена задержка подключения пользователей до 16 минут и каскадный эффект на доступность гильдии — то, что не было видно по метрикам и логам. Численных SLA-улучшений не приводится, но качественно система получила диагностический сигнал там, где раньше была тишина. Подход выглядит прагматичным: сохранить преимущества actor-модели и добавить трассировку через обёртку и строгий контроль стоимости.

Читать больше — InfoQ

×

🚀 Deploy the Blocks

Controls: ← → to move, ↑ to rotate, ↓ to drop.
Mobile: use buttons below.