Лучшие практики распределенной трассировки

Best practices for distributed tracing

Распределенное трассирование теперь является неотъемлемой частью современного стека наблюдаемости. С переходом к микросервисам нам понадобился новый способ отслеживать, как взаимодействуют наши сервисы. Распределенное трассирование предоставляет такую возможность, позволяя нам сделать трассировку запросов – т.е. отследить запрос через компоненты в нашей распределенной системе. Сегодня распределенное трассирование используется для выявления узких мест производительности, отладки проблем и понимания того, как наши системы взаимодействуют в производстве.

Однако реализация распределенного трассирования сложна, и то, сколько ценности команды получают от него, в значительной степени зависит от того, как он реализован. Механика реализации, такая как инструментирование компонентов, скорость выборки и качество визуализации трассы, все это влияет на ценность, которую компании получают от трассировки, что в свою очередь влияет на принятие разработчиками. Кроме того, этот пространство постоянно развивается, появляются новые инструменты и техники.

В этой статье давайте рассмотрим лучшие практики распределенного трассирования в 2023 году.

Что такое распределенное трассирование?

Распределенное трассирование относится к механизму, который позволяет нам отслеживать один запрос по мере его прохождения через несколько сервисов в распределенной среде.

Почему нам нужно распределенное трассирование.

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

Каждый сетевой вызов, сделанный в пути запроса, регистрируется и представляется в виде спана. Спан – это основная единица трассы – он представляет собой одно событие в трассе, и трасса может содержать один или несколько спанов. Спан состоит из сообщений журнала, данных, связанных со временем, и других атрибутов, чтобы предоставить информацию о операции, которую он отслеживает.

Анатомия распределенной трассы.

Благодаря своему уникальному виду, распределенное трассирование открывает несколько новых сценариев использования/улучшает существующие сценарии использования. Оно позволяет нам понять взаимозависимости сервисов (например, кто вызывает мой сервис), выявить узкие места производительности (какой конкретный вызов БД снижает мою задержку?), быстро определить точки сбоя для отладки (какой API вызывает эту проблему 500?) и также иметь более детализированные цели обслуживания.

Компоненты системы распределенного трассирования

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

  1. Библиотека инструментирования
  2. Коллектор (предварительный обработчик)
  3. Хранилище данных
  4. Слой визуализации

Сегодня существует несколько вариантов для каждого из этих компонентов – вы можете использовать одну платформу, которая выполняет все четыре вышеуказанных компонента, или собрать собственную систему распределенного трассирования, используя разные решения для разных компонентов.

Компоненты системы трассировки.

Библиотека инструментирования

Это часть, которая интегрируется в каждое приложение или сервис. Когда приложение выполняется, библиотека инструментирования гарантирует, что в каждый запрос добавляются идентификаторы трассировки или что контекст трассировки (ID трассировки) передается в следующий спан. Библиотека отправляет эти данные коллектору.

Коллектор

Коллектор является посредником между библиотекой инструментирования и хранилищем данных. Он собирает трассы, обрабатывает их (например, агрегирует спаны, выбирает выборку) и подготавливает их для сохранения.

Хранилище данных

Хранилище данных сохраняет и индексирует трассировочные данные. Обычно оно использует распределенную систему хранения, способную обрабатывать большие объемы данных и обеспечивающую эффективный запрос и извлечение данных.

Слой визуализации

Это пользовательский интерфейс распределенной системы трассирования. Он позволяет разработчикам и операторам взаимодействовать с данными трассировки. Этот слой предоставляет инструменты для запроса, поиска и фильтрации данных трассировки на основе различных критериев. Он представляет данные трассы в визуально понятном виде, часто в виде графа трассы или временной шкалы, что позволяет пользователям анализировать последовательность событий и выявлять узкие места или проблемы.

Реализация систем распределенного трассирования сложна

Хотя есть несколько преимуществ, реализация систем распределенного трассирования (особенно хорошо) все еще не является простой, “решенной” задачей. Для этого требуется, чтобы реализующая команда принимала несколько решений, и эти решения имели существенное влияние на количество ценности, которую остальная команда инженеров получает от трассировки. Не редкость, когда компании внедряют распределенное трассирование и платят полмиллиона долларов ежегодно, чтобы разработчики использовали его только дважды в год. См. ниже некоторые лучшие практики по реализации хорошей трассировки.

Лучшие практики распределенного трассирования

Выберите OTel для инструментирования

Существуют несколько популярных open-source фреймворков для трассировки, таких как OpenTelemetry, Jaeger и Zipkin. Сегодня, в 2023 году, OTel стал вполне очевидным выбором по следующим причинам:

  • Широкий охват: OTel имеет библиотеки инструментирования и SDK для разных языков программирования и фреймворков, и имеет широкий охват. Смотрите здесь, чтобы узнать, что поддерживает OTel.
  • Нейтральность поставщика: К настоящему времени большинство поставщиков поддерживают инструментирование OTel. Вы можете инструментировать с OTel и отправлять данные к любому поставщику, который вам нравится. У вас будет совместимость и переносимость поставщика в течение времени (если вы решите сменить поставщика). Вот список поставщиков наблюдаемости, которые нативно поддерживают данные OTel, а здесь – реестр библиотек и плагинов для подключения OTel к другим поставщикам.
  • Зрелость и стабильность: OTel зрелеет несколько лет, с широкой поддержкой сообщества. Сейчас это второй по величине проект в экосистеме CNCF по количеству участников, следующий только за самим Kubernetes. Сильное сообщество обеспечивает его дальнейшее развитие и быструю поддержку новых технологий.

Используйте автоматическую инструментализацию, где это возможно

OpenTelemetry предоставляет два способа инструментирования кода в приложениях и компонентах – ручное инструментирование и автоматическое инструментирование. Если вы используете Kubernetes и большинство ваших сервисов написано на Java, NodeJS или Python, активно используйте автоматическую инструментализацию, так как она сокращает усилия по реализации.

Ручное инструментирование

Код OTel должен быть добавлен в приложение разработчиком, поэтому это требует изменения кода. Ручное инструментирование позволяет настроить создание спанов и трассировок. Большинство языков поддерживают ручное инструментирование – C++, .NET, Go, Java, Python и т.д. Смотрите здесь для последнего списка.

Автоматическое инструментирование

Это способ инструментализации приложений/сервисов без изменения кода или перекомпиляции приложения. Интеллектуальный агент подключается к приложению, считывает его активность и извлекает трассировки. Это возможно, если вы используете Kubernetes. OTel сейчас поддерживает автоматическую инструментализацию для Java, NodeJS, Python и т.д. (смотрите здесь для последнего списка). Настройка спанов и трассировок ограничена в автоматической инструментализации (по сравнению с ручной), но достаточна для большинства случаев использования.

Начните с критических путей и расширяйтесь оттуда

Неразумно инструментировать каждый сервис/компонент в больших распределенных системах сразу, поэтому важно тщательно выбирать, с каких путей начать инструментирование и как расширяться оттуда. Некоторые руководства/принципы, которых следует придерживаться:

Идите извне-внутрь/Начните с ближайших к пользователям точек входа

Часто лучше начинать снаружи и двигаться внутрь. Это означает начинать с точек, где запросы входят в ваше приложение, входящие запросы от пользователей или внешних клиентов. Начиная с точек входа, легче получить комплексное представление о том, как запросы протекают через систему.

Выберите самые важные пути в системе и сначала инструментируйте их

Общее руководство заключается в определении наиболее важных путей запросов в вашей системе; это могут быть наиболее часто используемые или имеющие наибольшее влияние на общую производительность приложения мониторинга. Начните с инструментирования этих критических путей сначала, чтобы продемонстрировать ценность всей организации, а затем расширяйтесь оттуда.

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

Независимо от выбранных путей, убедитесь, что путь инструментирован от начала до конца – это означает, что каждый сервис и компонент в пути запроса инструментирован для передачи контекста (TraceID) и создания спанов по мере необходимости. Любые пробелы приводят к неполным или разорванным трассировкам, что уничтожает усилия, вложенные в инструментирование вышестоящих сервисов.

Будьте целенаправленными в отношении выборки

В 99% случаев компании хотят выборочно отслеживать свои трассировки. Это связано с тем, что если вы сохраняете каждую трассировку, вы можете хранить и управлять огромным объемом данных.

Давайте рассмотрим пример. Предположим, что каждый спан занимает 500 байт (включая тегирование и журналирование). Если ваше приложение обслуживает 2000 запросов в секунду и имеет 20 различных сервисов, оно генерирует 20 МБ данных каждую секунду, или 72 ГБ в час, или 1 ТБ в день, для простой конфигурации с 20 сервисами.

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

В целом, существует две категории выборки:

1. Передний / основанный на голове выбор

Это простой способ решить, какие трассы сохранить до того, как будут сгенерированы какие-либо трассы для данного запроса. Это называется выборкой, основанной на голове, поскольку решение принимается в начале или “голове” запроса. Иногда это называется безпристрастной выборкой, когда решения принимаются даже без просмотра запроса. В рамках выборки на основе головы обычно используются несколько распространенных механизмов, например, ниже.

  • Вероятностная или фиксированная выборка по крейту: Случайный выбор подмножества трасс для сохранения на основе фиксированной скорости выборки – скажем, 1%
  • Ограничение выборки по скорости: Задание фиксированного лимита на количество запросов, которые должны быть трассированы за единицу времени. Например, если лимит скорости установлен на 100 запросов в минуту, будут трассироваться только первые 100 запросов за эту минуту.
  • Выборка на основе приоритетов: Выборка на основе приоритетов назначает разные приоритеты запросам, и скорость выборки соответствующим образом корректируется. Запросам с более высоким приоритетом (например, критическим транзакциям) назначается более высокая скорость выборки, а запросам с более низким приоритетом – более низкая скорость.

2. Выборка на основе хвоста

Выборка на основе хвоста происходит на основе ответов внутри трассы, например, высокой задержки и ошибок. Этот метод гарантирует трассировку “интересных” запросов, даже когда общие скорости выборки низки. Однако выборка на основе хвоста гораздо сложнее реализуется (по сравнению с другими более простыми методами), так как требуется хранить в буфере все трассы до получения ответа. В этом руководстве подробно рассматривается выборка на основе хвоста.

Большинство организаций обычно прибегают к простому механизму вероятностной выборки на основе головы с скоростью выборки 1-3%. См. здесь, как настроить фиксированную скорость выборки в OTel.

Будьте избирательны при реализации пользовательской трассировки

Распределенная трассировка мощна тем, что позволяет нам создавать пользовательские трассировочные спаны. Пользовательские спаны позволяют обогатить распределенные трассы дополнительной доменной информацией, делая данные трассировки более значимыми.

Возможно захватить и регистрировать состояния ошибок в рамках спана или создать дочерние спаны, которые дополнительно описывают работу сервиса. Эффективно помеченные спаны, в свою очередь, могут значительно сократить количество необходимых журнальных записей в вашем коде.

В контексте трассировки ширина относится к количеству сервисов или компонентов, которые производят инструментирование, а глубина относится к уровню детализации, захватываемому в каждом спане. Нахождение правильного баланса между широтой и глубиной является ключевым при реализации эффективного механизма трассировки при одновременном контроле затрат.

В общем случае, хорошей идеей является расширение до максимально возможной ширины и избирательное углубление.

Интегрируйте трассировку с вашими системами мониторинга и регистрации

Убедитесь, что вы связываете трассировку с существующими системами мониторинга и регистрации, чтобы упростить разработчикам корреляцию между этими тремя наборами данных при устранении неполадок. Обычно это делается через:

  • Внедрение журналов: Внедрение идентификаторов трассировки / идентификаторов спанов непосредственно в журналы с использованием фреймворков или библиотек журналов. Таким образом, каждое сообщение журнала имеет идентификатор трассировки, который можно использовать для удобного запроса конкретных журналов.
  • Метки метрик: Связанные с трассировкой метки или ярлыки могут быть включены при записи метрик. Эти метки могут быть идентификаторами трассировки, именами спанов или другой специфичной для трассировки метаданными. Это позволяет разработчикам фильтровать и агрегировать метрики вокруг данных трассировки и упрощает понимание распределенных систем.

Протоколы, такие как OpenTelemetry, уже позволяют вам делать это легко.

Выберите современный интерфейс визуализации трассировки

Существует значительная разница между решениями в терминах интерфейса. После сбора данных трассировки вам нужно иметь возможность их визуализации. Хорошая визуализация трассировки позволит вам видеть поток трассировочных запросов через систему и определять узкие места производительности.

Однако все инструменты трассировки не предоставляют интуитивный и удобный способ визуализации и анализа этих данных непосредственно. Некоторые инструменты отличаются сбором и хранением данных трассировки, но имеют основную визуализацию (например, Jaeger, Zipkin, AWS XRay), в то время как другие больше ориентируются на предоставление информации из данных трассировки и, как результат, инвестируют в более сложную визуализацию и аналитику (например, Honeycomb, Lighstep, Helios).

Хорошие инструменты визуализации должны предлагать готовые панели инструментов, которые автоматически предоставляют вам карты зависимостей службы, имеют визуализацию трассировки Ганта и водопада, а также позволяют выполнять детальные запросы и фильтрацию трассировок. Эта статья представляет собой всестороннюю точку зрения на визуализацию в распределенной трассировке.

Исследуйте инструменты следующего поколения, которые объединяют искусственный интеллект и трассировку

С развитием OTel инструментирование стало стандартизированным. Аналогично, хранение и запросы также широко коммодизировались в отрасли наблюдаемости за последние несколько лет. Сегодня есть некоторые отличия в слое визуализации и аналитики, хотя даже это не имеет особого значения.

Существует новый класс решений, которые используют искусственный интеллект на данных распределенной трассировки для получения выводов о причинах проблем. Эти решения также имеют самый современный стек трассировки и значительно упрощают реализацию и управление. Например, решения, такие как ZeroK, позволяют вам:

  • Установить распределенную трассировку для всех компонентов сразу без изменения кода; все службы, базы данных и очереди сразу покрываются с использованием OTel и eBPF.
  • Они устраняют необходимость в выборке – они обрабатывают 100% трассировок и с помощью искусственного интеллекта автоматически идентифицируют аномальные/ “интересные” трассировки для хранения (например, трассировки ошибок, трассировки с высокой задержкой).
  • Добавлять аномальные трассировки с дополнительным контекстом (например, журналы) для помощи в отладке по мере необходимости.
  • Применить LLM к этим трассировкам для автоматического определения вероятных причин проблем в производстве.

Инвестируйте в обучение разработчиков

Это часто недооцениваемый, но критически важный фактор, который будет определять успех распределенной трассировки в вашей организации. Помните, что распределенная трассировка является сложной, и новым разработчикам сложно разобраться, как эффективно ее использовать. Не редкость, когда компании имеют всего несколько активных пользователей, использующих платформу трассировки, и то только несколько раз в квартал.

Разработчикам необходимо научиться интерпретировать данные трассировки, понимать взаимосвязи между различными микросервисами и устранять проблемы с помощью инструментов распределенной трассировки. Им необходимо руководство по bewt-практикам, таким как согласованные соглашения о наименовании, правильная инструментация и понимание распространения контекста трассировки. Планирование обучения разработчиков по распределенной трассировке – это стратегическая инвестиция. Оно не только ускоряет интеграцию трассировки в систему, но также способствует развитию культуры, где разработчики активно участвуют в непрерывном улучшении видимости, надежности и производительности системы.

Заключение

Мы рассмотрели лучшие практики распределенной трассировки и то, что можно сделать, чтобы сделать путь более простым. Распределенная трассировка больше не является новинкой; она превратилась в неотъемлемую часть стека наблюдаемости.