Конспект "Трейсинг распределенных систем. Егор Мыскин"

01.02.2019

Суть: Трейсинг упрощает дебаг и тестирование, внедрить его крайне просто.

ProppelerAds доставляет рекламу пользователям. Нагрузка на систему 200 000 запросов в секунду.

Зачем внедряли трейсинг

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

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

Чего хотели

  • Чтобы быстро работало
  • Логировало любые запросы
  • Можно было добавлять к запросам контекст
  • Видеть что тормозит

История трейсинга

  • В 2000 году Google представил Dapper, описав основные принципы трейсинга.
  • В 2009 году Twitter выпустил Zipkin.
  • В 2016-17 появился стандарт OpenTracing, на основе которых появилось open source решение. Google же выпустил OpenCensus.

Как работает трейсинг

Приходит запрос от пользователя, запросу присваивается id, который передается дальше всем сервисам, а сервисы отправляют данные о запросе в коллектор.

Trace-ID виден в хедере всех запросов, по нему можно искать в UI. Еще можно добавить TraceGroup(это как теги). По этим тегам группируются множества трейсов, это облегчает дебаг сложных страниц с множеством запросов.

Что такое трейс

Трейс — записанный запрос пользователя с длительностью. Он состоит из span`ов — запросов в другие сервисы, базы, вызовы функций и т.п. Они имеют иерархическую вложенность, контекст каждого span можно наполнять какими-то данными и метриками.

В качестве коллектора в компании используется Jaeger, который написан на go. Этот коллектор занимается складированием span’ов. Стораджем может быть Cassandra или ElasticSearch.

В каждый хост/контейнер по udp отправляет span-ы в jaeger-agent, который по Thrift протоколу отправляет все в jaeger-collector. Коллектор все складывает с сторадж, информацию из которого отображает Jaeger UI.

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

На основе span’ов Jaeger строит граф зависимостей сервисов.

Практики внедрения

В PropellerAds используют OpenCensus, потому что большая часть бекенда написана на go, а с ним у OpenCensus хорошая интеграция. Так же у OpenCesus есть экспортеры для разных систем: Jaeger, Zipkin, Stackdrive. Есть готовые middleware для http, db, grpc. Поддерживает множество стораджей, интегрируется парой строчек в коде.

Сейчас в PropellerAds обрабатывается примерно 6-7 тысяч span в секунду на 1 инстансе Jaeger и двух инстансах Elastic.

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

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

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

Интегрировать во все сервисы на Go получилось буквально за пару вечеров.

Сложности внедрения

Не везде есть заголовки

Пришлось писать обертку над сообщениями для кастомных протоколов, кафки, где нет заголовков, передающих Trace-ID.

У локального агента есть ограничения на размер датаграммы

Если приложение порождает очень много спанов, то их объем может не влезть в захардкоженный максимальный размер датаграммы, передаваемой по UDP, в локальный агент. Сейчас эта проблема агента исправляется, обойти можно прямой отправкой спанов в коллектор.

PHP

TraceID от Jaeger и TraceID в PHP отличались, из-за этого трейс разъезжался. Решается через установку bcmath для PHP и обновлением opencensus-php-exporter-jaeger до 0.1.1 Так же для PHP нужно пересылать все по UDP, потому что PHP блокирующийся язык, а UDP позволяет нам не ждать отправки запроса.

Примеры использования

Дебаг

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

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

Тестирование

Трейсинг облегчает интеграционное тестирование, за счет того тестировщик может отдать разработчику Trace-ID, по которому разработчик продолжить дебажить. Некоторые тестировщики теперь даже могут исправлять проблемы, по трейсингу они понимают, как система работает.

Вопросы из аудитории

Как внедрять tracing для MySQL, Rabbit и т.п?

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

Как сматчить то что происходит в коде с состоянием железа?

Диагностировать внутренние проблема tracing не позволяет, но можно в его метадате посмотреть на каком сервере он выполняется.

Правда, что Jaeger позволяет практически полностью избавиться то логов?

Если вы агрегируете логи для счетчиков и делаете алерты, то трейсинг это заменить не сможет, алертов тут нет. Но такие вещи можно вынести в мониторинг, оставить системные логи, а все остальное покрыть tracing`ом.

Какой процент overhead`а привносить tracing?

3-5% на сборку мусора в go. На графиках распределения запросов по времени ответа в 99 перцентиле нет никакой разницы. Разница может появится в случае складывания больших данных и большом проценте семплирования при большом количестве запросов.

Обязательно ли все это разворачивать или есть облачные решения?

Можно использовать StackDrive от Google.

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

Для первого добавления хватит подключения внешнего сервиса к middleware. Это покроет 80-90% проблем.

Как вы нашли проблему с аналитикой?

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

Ссылки

Я консультирую о том о чем пишу, связаться со мной можно через telegram @aladmit или по почте [email protected]

Подпишись, чтобы не пропустить новые статьи Telegram