OpenTelemetry под нагрузкой: что ломается первым
Распределённая трассировка редко падает в одном месте. Сначала растут очереди и память Collector, затем теряются спаны, а после этого замедляется само приложение. Разбираем порядок отказов и план проверки.

При росте нагрузки распределённая трассировка ломается не там, где её обычно ищут. Сначала OpenTelemetry Collector начинает накапливать очередь, затем упирается в память или канал экспорта, а приложение получает дополнительную задержку от создания спанов. Универсального порядка нет: он зависит от размера спана, доли сэмплирования, числа атрибутов, схемы доставки и поведения backend. Поэтому под нагрузкой нужно проверять не только наличие трасс, но и цену каждой сохранённой трассы.
Что именно происходит с трассой
Сервер создаёт span для входящего запроса, добавляет к нему атрибуты и события, передаёт контекст следующему сервису и отправляет данные через SDK-экспортёр. Чаще всего приложение не пишет телеметрию напрямую в хранилище: данные уходят в OpenTelemetry Collector, а уже он принимает, обрабатывает и экспортирует их в backend.
У каждой трассы есть несколько стадий с собственными ограничениями:
- приложение тратит CPU и память на создание спанов, сериализацию и передачу данных;
- приёмник Collector ограничен числом входящих соединений и скоростью обработки протокола;
- процессоры расходуют память на батчи, группировку и tail sampling;
- очередь экспорта накапливается, если backend отвечает медленнее, чем приходят данные;
- хранилище платит за объём, индексацию и высокую кардинальность атрибутов.
Потеря спана и потеря всего запроса — разные события. При переполнении буфера обычно исчезает часть телеметрии, а бизнес-запрос продолжает работать. Но если SDK-экспортёр синхронный или неправильно настроен, задержка доставки может попасть в критический путь запроса.
Трассировка под нагрузкой должна деградировать предсказуемо: сначала уменьшать полноту наблюдений, а не превращать систему в источник собственной аварии.
Ключевой термин
Backpressure[1] — ситуация, когда потребитель данных обрабатывает их медленнее производителя. В OpenTelemetry это видно по растущей очереди, времени экспорта и числу отброшенных элементов.
Что ломается первым
Ниже не рейтинг для любой инсталляции, а типичный сценарий для схемы «сервис — Collector — удалённый backend». Если Collector расположен рядом с приложением, а backend доступен по быстрой сети, первым может оказаться не сеть, а лимит памяти или CPU.
1. Кардинальность атрибутов
Проблема начинается ещё до заполнения диска. Команда добавляет в каждый span URL, идентификатор пользователя, UUID заказа, текст ошибки или query string. Для отладки это удобно, но такие значения создают огромное количество уникальных комбинаций. Backend тратит ресурсы на индексацию, а объём данных растёт пропорционально числу запросов и атрибутов.
Особенно опасны сырые URL: /users/184927/orders/7f... хуже нормализованного маршрута /users/{id}/orders/{order_id}. Секреты и персональные данные при этом могут случайно попасть в трассу.
Проверяйте не только средний размер span, но и распределение: p95 и p99 размера, число атрибутов на span, долю уникальных значений и объём данных по сервисам. Снижение sampling не лечит высокую кардинальность у тех трасс, которые всё-таки сохраняются.
2. Очередь и память Collector
Когда экспортёр не успевает отправлять данные, очередь растёт. Batch-процессор уменьшает число сетевых запросов, но не отменяет ограничение по памяти: каждый ожидающий элемент должен где-то храниться. Tail sampling требует ещё больше состояния, потому что решение о сохранении принимается после получения всей или значительной части трассы.
Первый тревожный сигнал — рост использования памяти вместе с увеличением размера очереди. Следом появляются сбросы, перезапуски по OOM и разрывы трасс: часть спанов уже ушла, часть осталась в буфере или была отброшена.
3. Медленный экспортёр и сеть
Collector может принимать телеметрию быстрее, чем backend подтверждает её запись. Причина бывает в лимитах удалённого сервиса, TLS, DNS, перегруженном прокси, коротких таймаутах или слишком большом размере батча. При нескольких экспортёрах узкое место одного из них способно занять общий пул ресурсов.
Важно разделять ошибки доставки и потерю данных до Collector. Если счётчик входящих спанов растёт, а счётчик успешно экспортированных стоит на месте, проблема после приёма. Если не растёт уже приёмник, смотрите сеть, протокол и SDK в приложении.
4. CPU приложения и задержка запроса
Инструментация добавляет работу на каждый входящий запрос: создаёт объекты, копирует атрибуты, поддерживает контекст и иногда сериализует данные. На редких запросах это незаметно. На коротком endpoint с высокой частотой вызовов накладные расходы могут стать сопоставимыми с бизнес-логикой.
Сравнивайте четыре режима на одинаковом трафике: без инструментации, с созданием спанов без экспорта, с обычным sampling и с экспортом через Collector. Если задержка появляется уже во втором режиме, искать её нужно в SDK или количестве создаваемых спанов, а не в backend.
Два способа доставки и их цена
На практике встречаются две базовые схемы. При локальном агенте приложение отправляет данные на Collector на том же узле или в том же окружении. При центральном шлюзе сервисы отправляют телеметрию на общий пул Collector. Обе схемы поддерживают OTLP; различается цена отказа.
| Схема | Что выигрываете | Где платите | Что проверять под нагрузкой |
|---|---|---|---|
| Локальный Collector | Короткий сетевой путь, изоляция от проблем удалённого backend | Больше процессов и суммарного потребления памяти | Лимит CPU и памяти на узле, поведение при рестарте агента |
| Центральный Collector | Единая настройка, проще масштабировать и обновлять | Сеть становится частью критического пути доставки | Балансировку, лимиты соединений, очередь и распределение по экземплярам |
| Прямой экспорт из приложения | Меньше компонентов | Backend и сеть сильнее влияют на задержку сервиса | Таймауты, повторные отправки, блокирующие вызовы и потерю данных |
Для сервисов с жёсткими требованиями к задержке локальный Collector обычно проще изолировать от отказа backend. Центральный пул разумен, когда инфраструктура уже умеет контролировать его очереди, лимиты и масштабирование. Прямой экспорт стоит оставлять только там, где поведение SDK и экспортёра проверено на реальном профиле трафика.
Как проводить замер, а не гадать
Без исходных цифр нельзя честно сказать, что именно сломается у вашей системы первым. Нужен повторяемый тест: фиксированная версия приложения и Collector, одинаковое железо, одна схема сети, заданная длительность и два-три уровня параллельности.
- Зафиксируйте нагрузку. Запишите число запросов в секунду, размер ответа, долю ошибок и распределение latency. Тестируйте не только среднее значение, но и p95/p99.
- Снимите базовую линию. Запустите сервис без трассировки и сохраните CPU, память, сетевой трафик и задержку. Без базы нельзя оценить цену инструментации.
- Добавляйте телеметрию по слоям. Сначала включите создание спанов, затем экспорт, затем обработчики и tail sampling. Между этапами меняйте только один параметр.
- Намеренно замедлите backend. В тестовой среде ограничьте канал или добавьте задержку на приёмнике. Смотрите, как быстро растёт очередь и когда появляются сбросы.
- Проверьте восстановление. Остановите backend на несколько минут, затем верните его. Система должна либо постепенно разгрузить очередь, либо предсказуемо отбросить новые данные, не уйдя в бесконечный рост памяти.
На каждом прогоне фиксируйте объём принятых, экспортированных и отброшенных спанов. Полезная трасса без этой статистики создаёт иллюзию контроля: на экране есть отдельные успешные запросы, но неизвестно, сколько данных не дошло.
Где подход ломается
Tail sampling не является бесплатным фильтром
Head sampling принимает решение в начале запроса и сразу сокращает поток. Tail sampling ждёт, пока соберётся достаточно информации о трассе: например, чтобы сохранить ошибки и медленные запросы. За это приходится платить памятью, временем ожидания и сложностью маршрутизации всех спанов одной трассы к одному обработчику.
Если потерян корневой span или часть дочерних спанов пришла после истечения окна ожидания, итоговая трасса будет неполной. Поэтому tail sampling нужно проверять на длинных запросах, ретраях и асинхронных операциях, а не только на коротком HTTP-вызове.
Ретраи могут усилить аварию
Повторная отправка помогает пережить кратковременный сбой backend, но при длительной недоступности увеличивает сетевой трафик и удерживает данные дольше. Очередь, ретраи и большой batch в сочетании способны превратить временный отказ в OOM. Ограничения должны быть конечными, а политика потери данных — заранее принятой.
Сэмплирование скрывает редкие ошибки
Если решение принимается случайно и до появления ошибки, редкий сбой может не попасть в сохранённую выборку. Для диагностики обычно нужны отдельные правила для ошибок, долгих запросов и выбранных критичных маршрутов. Но каждое исключение увеличивает объём данных, поэтому его надо оценивать в гигабайтах и стоимости хранения.
Что ревьюить в конфигурации
- Есть ли конечные лимиты на размер очереди, batch и память.
- Понятно ли, что происходит при недоступности backend: блокировка, сброс или временное накопление.
- Не отправляются ли в атрибутах токены, cookies, query string и персональные данные.
- Нормализованы ли маршруты и имена операций, чтобы динамические идентификаторы не стали частью ключа.
- Разделены ли метрики самого Collector и метрики приложения.
- Есть ли алерты на долю отброшенных спанов, ошибки экспорта, рост очереди и память.
Не смешивайте проблему трассировки с инвалидацией кеша, профилированием CPU и анализом логов. Эти сигналы дополняют друг друга, но имеют разные бюджеты и разные точки отказа.
Что делать дальше
Начните с небольшого нагрузочного стенда и соберите базовую линию без OpenTelemetry. Затем проверьте локальный и центральный Collector на одном профиле запросов, отдельно отключая экспорт и меняя sampling. В проде первым делом поставьте наблюдение за памятью Collector, размером очереди, временем экспорта и долей отброшенных спанов. Если этих четырёх показателей нет, вы узнаете о поломке трассировки только по пустому экрану в backend.
Проверка рекламы на риски: Что в макете вызовет вопросы ФАС: превосходные степени, сравнения, обещания результата, маркировка.
Спросить за 40 ₽Источники: OpenTelemetry Collector documentation, OpenTelemetry sampling concepts
Частые вопросы
Можно ли включить OpenTelemetry на всех запросах без sampling?
Что произойдёт, если backend трассировки недоступен?
Почему трассы в backend неполные, хотя ошибок экспорта нет?
Нужен ли Collector, если сервисов мало?
Как понять, что проблема в высокой кардинальности атрибутов?
Какие версии учитывает этот разбор?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.