Для многих разработчиков процесс релиза их продукта похож на выбрасывание слепого котёнка в пасти диких псов. После этого главная задача авторов — отбиваться от случайно долетевших до них багов. На самом деле, приложение не заканчивает свой жизненный путь в зубах пользователей, а только начинает его. И ему нужна помощь разработчиков не меньше, чем во время становления и тестирования.
В этой статье мы рассмотрим, каким образом можно наблюдать за работой продукта и его боевым окружением, научимся собирать жизненно необходимые метрики и представлять их в удобоваримом виде. Узнаем, что такое Time Series и как они могут помочь нашим и сторонним приложениям в процессе диагностики. Подробно познакомимся с лидерами рынка инструментов для мониторинга, специализированным хранилищем InfluxDB и системой визуализации данных Grafana.
Прототипом статьи является доклад Анатолия Кулакова на DotNext 2017 Moscow. Анатолий получал образование специалиста по информационной безопасности, затем зарабатывал как суровый C++ разработчик под Linux. Когда надоело кодировать и захотелось творить, перешёл на C#. Пишет на .NET с первых его версий. Занимается проектированием и построением бизнес-приложений, распределённых и отказоустойчивых систем. Отдыхает с ES, CQRS и DDD.
Перед просмотром можно загрузить слайды в формате PDF.
Осторожно, трафик! В этом посте присутствует огромное количество картинок — слайдов и скриншотов с видео в формате 720p. На слайдах присутствует важный для понимания статьи код.
Поговорим о метриках. Почему именно о них? Дело в том, что в своей практике я сталкивался со множеством проектов, и меня всегда возмущала ситуация, что большинство команд даже не задумываются о том, что сейчас творится на их продакшне. Они просто выпустили продукт, и, по их мнению, он летит. В реальности это совсем не так, сервер может захлебываться от наплыва пользователей, могут отказывать диски, может твориться всё, что угодно. И, в большинстве случаев, об этом никто не подозревает и не знает.
К сожалению, таким образом сложилась наша культура разработчиков, что для нас главным моментом является именно процесс написание кода. Но это всего лишь маленькая часть живого продукта, поэтому со временем эта тенденция меняется, чему я весьма рад. Мы уже знаем такие страшные ругательные слова, как CI и DI, они уже не вызывают дрожь в коленках. Мы привыкли, что системы контроля версий, ведения задач, процесс планирования и тестирования являются неотъемлемой частью современного проекта.
Следующим большим шагом в данном направлении является выход за периметр своей уютной команды и нанесение добра на территории непосредственного пользователя. И это очень интересный процесс, ведь почти всегда пользователи не ведут себя с нашими программами так, как мы планировали, и обычно наши программы не готовы к тому безумству идей, на которые способны эти гении мысли. Поэтому после того, как мы начинали наблюдать за реальным использованием наших продуктов, мы обязательно открывали для себя большой интересный и увлекательный мир, полный безумия и непредсказуемости. Оказывалось что все наши оптимизации не использовались из-за случайной нелепицы, основная нагрузка приходится не на тот сервис, на который мы рассчитывали, злобные админы искусственно ограничивают ресурсы для нашего приложения, лоад балансер распределяет запросы неравномерно и т.д. Огромное количество непредсказуемых ситуаций подбрасывает нам жизнь.
Большинство из них оседают в раскаленной психике уставших пользователей. Остальные оформляются в невнятных багах, описывающих результат, по которому совершенно невозможно понять причины происшедшего. Гораздо лучше с любой стороны иметь постоянный мониторинг важных сервисов в реальном времени и понимать, чем они сейчас занимаются.
Мониторинг способен не только поведать вам о проблемах и нагрузках, он также является прекрасной площадкой для аналитики и предсказаний. Именно этим мы с вами и займемся. Разберемся, как и какими средствами можно реализовать абсолютно любые ваши вуайристические фантазии.
Я уверен, что когда я описывал суть проблемы, многие подумали о логировании. Действительно, можно удалённо собрать логи, проанализировать их и сделать выводы, а что же там такое творится на этом вашем продакшне. И это недалеко от истины. На самом деле, это родственные инструменты, которые решают схожие задачи. Если вам интересно послушать введение о правильном современном логировании, то рекомендую обратить внимание на доклад "Structured logging".
Но в этой статье мы сфокусируемся именно на метриках. Чем же отличаются метрики и логирование? Итак, основное содержимое логов — это любая информация об окружающем мире, бизнес-процессе, ожиданиях и ошибках. Если вы знаете, как готовить их правильно, то без труда сделаете аналитику по их содержимому. Но существует огромный пласт задач, в котором гибкость и мощь логирования являются избыточным явлением, и даже больше – вредят.
Например, вам хочется постоянно наблюдать за загрузкой процессора. Конечно, можно эту информацию каждую секунду записывать в логи, а потом анализировать. Но тут мы сталкиваемся с целым рядом проблем, основные из которых — это объём данных и скорость их обработки. Количество счётчиков, за которыми мы захотим наблюдать, легко начинается с десятков (процессор, память, GC, запросы, ответы). А в крупных проектах без особых усилий доходит до сотен.
Представьте, что у вас есть двести хостов, и они снимают по сто метрик каждые десять секунд. При условии того, что у нас в сутках 86 400 секунд, мы ежедневно будем получать в своих логах 172 800 000 значений.
Только представьте, во что превратятся ваши логи, если каждую секунду вы будете сливать в них тысячи метрик с низкоуровневой, безликой, неинтересной информацией. Во-первых, от логов всё-таки ожидается челове-читабельность и логичность повествования, а не гора инфраструктурного шума. Но эта проблема легко решается с помощью семантических фильтров. А вот тот размер информации, который теперь обязаны обрабатывать инструменты, создававшиеся с другими целями, — это уже проблема. Проблемы с производительностью будут на всех уровнях: в обработке, передаче, хранении, аналитике. И это чистая обыденность, существует куча других областей с несоизмеримо большими аппетитами, таких как: атомные станции, заводы, или, например, интернет вещей, где, по заявлениям бородатых аналитиков, к 2020-му году на каждого человека будет приходиться по шесть устройств, которые нужно будет постоянно мониторить.
И если мы говорим об абсолютном объёме, то размер данных, необходимых для работы с метриками, сильно превышает размер обычных логов. Всё это наводит на мысль, что нельзя для логов и метрик использовать одни и те же решения. Поэтому человечество выделило из логов такое понятие, как метрики. И разделило работу с этими данными на две независимые части, со своими инструментами, алгоритмами и подходами. И, как показывает тенденция последних 2-х лет, решение было абсолютно верным.
Если вы когда-либо слышали о росте популярности графовых или документо-ориентированных баз данных, всё это — детский лепет по сравнению с тем хайпом, который происходит вокруг баз данных для метрик. Метрики описываются временными рядами (Time Series). Временной ряд – это последовательность некоторых значений, взятых из одного источника через определённый интервал времени. Т.е. это результаты периодических измерений чего-либо во времени. Например, этот график представляет собой результаты периодических измерений популярности баз данных, сгруппированных по модели хранения:
Типичным показателем того, что этот график относится к Time Series, — это наличие оси времени. Если она есть, то почти всегда график — TS. Для подтверждения давайте посмотрим другие примеры:
Еще один типичный пример — Яндекс.Метрика, которая показывает посещаемость вашего сайта.
Давайте разберемся подробнее, из чего состоят временные ряды на примере сетевого интерфейса:
- Прежде всего, это, конечно же, время, в которое считываются значения.
- Сами значения. Значений может быть несколько, в данном случае это количество пришедших/ушедших пакетов.
- Также бывает очень полезно к вашему значению добавить мета-информацию, описывающую, в каком контексте происходило действие. Для этого существуют теги. Им можно присвоить всё, что угодно, например имя хоста или сетевого интерфейса, на котором мы делали измерение.
Если проводить аналогию с реляционными базами данных, то совокупность всех этих трёх параметров можно представить в виде таблицы «Network».
В таком случае, время всегда будет её главным ключом, кластерным индексом. Теги будут индексированными колонками, по ним очень хорошо строятся агрегаты и делаются фильтры. Сами значения — это неиндексированные колонки.
Но, в отличие от баз данных общего пользования, TSDB обладают уникальной информацией — они знают о природе этих данных, что позволяет им делать неимоверные оптимизации. Именно поэтому базы данных общего пользования всегда будут оставаться далеко-далеко позади. Например, между авторами Time Series баз существует интересная метрика, с помощью которой они меряются между собой в размерах собственного превосходства: средний размер, необходимый для хранения одной записи. Давайте сходу прикинем:
Дата и время хранятся обычно в наносекундах, занимают восемь байт. Теги могут легко перевалить за 20 байт, и поле данных, допустим double (самый распространенный тип для значений, которые хранятся в TSDB), занимает восемь байт. Ну вот если хранить так бесхитростно, то одна запись у нас будет занимать около 40 байт. Как вы думаете, какими цифрами хвастаются лидеры? Два байта.
Всего-навсего два байта, чтобы упаковать все наши значения. И это не предел, лучшие сражаются в районе одного байта. Каким образом такое вообще возможно? Как, зная специфику происхождения данных, можно всё это уложить в два байта?
Первое, что приходит на ум, — это использование стандартных алгоритмов сжатия. Обычно это плохая идея, потому что они создавались для совершенно других объемов информации, и они требуют для своей работы контекст намного больше, чем мы можем себе позволить. Ну и работают они в 30-40 раз медленнее.
Мы пойдём другим путём. Начнём с тегов. Их размер в постоянном потоке данных можно уменьшить до нуля. Каким образом это делается? Мы просто перемножаем имя метрики со всеми ключами и значениями тегов и получаем несколько слотов хранения (в примере два):
Таким образом, мы переносим теги из области данных в область схемы. Именно поэтому значения тегов не должно быть представлено случайными числами, а должно укладываться в конечный словарь. Эта часть временных рядов называется «Серией». Серия сама по себе не хранит никаких данных, она постоянна во времени, что позволяет просто пренебречь её размерами. Таким образом теги у нас схлопываются в ноль.
Если серия не занимает место, то его занимают метка времени и значение. Начнем со времени. Все алгоритмы сжатия, которые работают над Time Series, основываются на том же принципе, что и колоночные БД. Они работают с одной колонкой, с непрерывным потоком однотипных данных. Время обычно хранится с точностью до наносекунд. В 8 байтах. Для сжатия колонки со временем можно применить Delta-of-delta compression. Это алгоритм, который рассчитывает на то, что данные со счётчиков обычно снимаются периодически через равные интервалы времени. Например, через каждые 5 секунд. Мы можем вычислить дельту между этими временами и найти интервал. Имея начальное время и интервал, мы может предсказать следующее значение в колонке.
Обычно интервал не изменяется, поэтому мы можем вычислить ещё раз дельту над значением первой дельты. И обычно получается ноль. Для хранение такого специального, часто встречающегося значения достаточно одного бита (ноль у нас во второй дельте или не ноль).
Не думайте, что это слишком большие допущения и в реальном мире такого нет. По данным Facebook, они смогли упаковать 96% всех своих времён в этот один нулевой бит. Естественно, есть алгоритмы устранения небольших дребезжаний времени, пропусков и т.д.
Значения счётчиков могут быть произвольного типа. Но на практике это почти всегда числа с плавающей точкой. Именно на них нацелена основная магия по уменьшению размера полей.
Значения могут быть разбросаны непредсказуемо, поэтому предыдущий трюк с двойной дельтой тут уже не пройдёт. Другой приём основывается на том знании, что все значения приходят от одного источника, а значит имеют одинаковую точность и похожую размерность. На практике это значит, что их бинарное представление будет весьма схожим. Т.е. если мы банально заксорим соседнии значения, мы получим весьма небольшое число значащих символов:
Его можно сохранить, используя куда меньшее количество бит, чем оригинальное значение. И рядом с ним сохранить количество ноликов с наименьшей стороны. Но на практике всё ещё веселее. По статистике Facebook, 51% всех значений совпадают с предыдущим, т.е. их XOR даст ноль.
И как вы, наверное, догадались, для хранения этого специального случая достаточно одного бита. И это ещё не всё, XOR в данном примере — это лишь самый банальный предсказатель. Существуют другие предсказатели, которые динамически подстраиваются под ваши текущие данные и таким образом способны предсказывать значения с очень высокой вероятностью, что в результате позволяет упаковывать в 1 бит даже весьма нетривиальные колебания.
Соответственно, если данные будут приходить с одним и тем же интервалом и никогда не будут меняться, мы можем упаковать это в два бита. Конечно, в реальном мире так не происходит, и на практике данные изменяются, что заставляет Facebook тратит 1.37 байт на одно значение. И это всего лишь при помощи тех примитивных алгоритмов, которые мы сейчас рассмотрели.
Это довольно интересные алгоритмы, про них можно говорить часами, но давайте вернемся с небес на землю и посмотрим на наше приложение и его окружение.
- Для нашего приложения важны, прежде всего, метрики, из-за которых оно способно работать. То есть, hardware, операционная система. Источником этих метрик выступают Performance Counters. В них вы найдете кучу полезной информации, начиная от CPU, места на диске, памяти и заканчивая более высокоуровневыми платформами, такими как: .NET, Garbage Collector, JIT, IIS, SignalR и так далее.
- Еще обычно существуют третьесторонние компоненты, с которыми мы взаимодействуем. И у всех нормальных третьесторонних игроков обязательно есть API статистики, которые мы можем вычитать: Seq, MongoDB, MS SQL — все эти продукты имеют такой API, при помощи которого вы можете прийти, запросить их состояние и посмотреть, например, как они себя сейчас чувствуют.
- Также не будем забывать про наши любимые ETW, там тоже много всего интересного, если вдруг вы не нашли в первых пунктах того, что искали, обратитесь к ним.
- И самые главные, самые высокоуровневые метрики, которые у нас есть — это, конечно же, метрики нашего собственного приложения, вашего бизнес-домена. Какого размера документ открывает пользователь, сколько пользователей залогинилось, среднее время бизнес-транзакции — вот это всё.
Как вы видите, источников информации довольно-таки много, и неудивительно, что существуют специальные программные средства, которые позволяют вам удобно собирать эту информацию, агрегировать ее и сохранять. Одно из таких средств — это агент Telegraf. В стандартную его поставку входят более сотни плагинов для мониторинга широкого спектра популярных программ. Системные счётчики, популярные базы данных, веб-серверы, очереди и ещё куча всего.
Большое сообщество, гибкие настройки, отличная система плагинов делают этот инструмент незаменимым помощником в мониторинге. Telegraf способен не просто собирать информацию из разных источников и форматов, а также способен обрабатывать и агрегировать её на клиенте, что может сильно уменьшить объём и нагрузку на центральный сервер.
Давайте посмотрим на практике, каким образом работает Telegraf. Начнем, как ни странно, с Grafana.
Я специально не упоминал Grafana до этого момента, чтобы вы поняли, насколько низок в неё порог входа. Всё, что вам нужно знать: Grafana — это графический веб-интерфейс, который способен визуализировать временные ряды из TSDB. У Grafana есть хранилище, в котором содержится много различных плагинов, готовых дашбордов для существующих популярных систем, разных data source и так далее, одним из них мы сейчас воспользуемся.
Найдем дашборд, который называется Influx Windows Host Overview, он нужен как раз для того, чтобы сделать дашборд для Telegraf под Windows.
Этот дашборд состоит из двух частей: первая — настройки самого Telegraf, здесь описано, какие Performance Counters и в каких форматах он должен репортить, чтобы его подхватила Grafana.
Копируем эти настройки, вставляем в настройки самого Telegraf:
Как видите, настройки довольно интуитивные и понятные, вы задаете имя счетчика производительности и настраиваете период опроса:
Всё это Telegraf собирает и отправляет в Influx.
Вернемся к нашему дашборду. Как я говорил, он состоит из двух частей, теперь поговорим про вторую. Вторая часть — это уникальный номер дашборда, копируем его, переходим к нашей локальной Grafana, импортируем дашборд 19:04 по этому уникальному номеру, в этот момент Grafana сходит в интернет, скачает дашборд и в следующую секунду покажет нам много интересной информации о нашей системе.
Здесь полная информация о тредах, процессах, использовании CPU, памяти, дисков, ваших сетевых интерфейсов, сколько пакетов к вам пришло, сколько ушло, количество хэндлов и так далее. Я специально залогировал все процессы в системе, но в вашем продакшн-коде вам нужно ограничиться только теми процессами, которые нужны для вашей работы.
Как я уже сказал, Telegraf взаимодействует с Grafana не напрямую, между ними есть Influx. InfluxDB — это самая популярная база данных временных рядов на данный момент.
Она очень быстро обогнала всех своих конкурентов и сейчас не собирается сбавлять обороты. И наши тесты показали, что это вполне заслуженно.
Давайте на примере Influx посмотрим на специфику данных, с которыми обычно работают TSDB, и что их отличает от реляционных баз данных:
- Во-первых, это миллионы дата-поинтов и миллионы серий. Это как если бы вы в вашей реляционной базе данных начали создавать миллионы таблиц и заполнять их миллионами значений, такое на практике довольно редко встречается. А для Influx это стандартная ситуация.
- Частая запись. Дело в том, что данные в метрики пишутся постоянно, даже если пользователь ничего не делает. Метрики пишутся о том, что он ничего не делает, до сих пор ничего не делает и так далее.
- Такая же ситуация и с чтением. Аналитика, дашборды, алертинг, все требуют постоянного чтения, поэтому здесь тоже очень большие нагрузки.
- Удаление. Оно происходит большими пачками, потому что главная причина удаления — это просто «протухание» данных.
- Обновлений почти что нет, и ими можно пренебречь.
В терминах CRUD Influx является CR-системой, для него очень важны быстрые создания и чтение данных. Обновления и удаления случаются очень редко и в довольно специфических и хорошо оптимизируемых ситуациях.
«Под капотом» она хранит данные в своём собственном формате time-structured merge-tree.
Это оптимизация всем известного log-structured merge-tree (LSM-дерево) применительно к временным рядам, который хорошо зарекомендовал себя на практике. Это структура данных, оптимизированная для быстрого доступа по индексу в условиях частых вставок. Применяемая, например, в логах транзакций практически всех современных БД.
Еще одним большим преимуществом Influx является SQL-подобный синтаксис запросов.
Почему это важно? Его предыдущие оппоненты очень сильно грешили плохой проработкой этого аспекта, они просили нас составлять запросы из такой богомерзкой смеси, как регулярные выражения, JSON и больная психика авторов. Это вообще невозможно было поддерживать, где-то через неделю вы приходите, смотрите на свои запросы, и у вас вытекают глаза. И именно нормальный синтаксис запросов позволил Influx выстрелить на массовую публику.
Если мы говорим о том, что у нас постоянно копятся данные, необходимо понимать, что мы с ними делаем. Для этого есть Retention policy (специальный механизм, который предполагает удаление данных через какой-то промежуток времени, если они вам не нужны). Но это слишком банально. Если это скрестить с такой фичей, как Continuous Queries (это что-то вроде materialized view, предрасчет сложных агрегатов на сервере), получится такой интересный механизм, как downsampling. Приведем пример.
Допустим, вы хотите измерять количество запросов, приходящих на ваш сайт. Вы вполне можете делать это в реальном времени, в графиках наблюдать загрузку всего этого и как-то на это реагировать. Через сутки real-time значения для вас являются избыточными, и вы вполне можете сагрегировать их до десятисекундных интервалов, вычислить агрегаты (min, max, count, какие вам интересны) и сохранить тот же набор данных, только в гораздо меньшем размере, следовательно, вы будете использовать гораздо меньше места. Через неделю вы можете увеличить период до одной минуты, через месяц — до часа, и оставить эти данные в архиве, например, для сравнения производительности вашего приложения через год.
По поводу производительности: прежде чем я назову цифры, здесь необходимо оговориться, что в такой узкоспециализированной сфере на производительность влияет абсолютно всё: количество метрик, насыщенность тегов, частота запросов, сложность аналитических алгоритмов, которые постоянно дергают Influx и читают эти данные. Самый банальный совет — всегда пробуйте на своих данных, на своем окружении и смотрите, что получится у вас. Но все-таки некоторые цифры хочется привести, чтобы вы понимали, зачем я об этом рассказываю:
Если вы довольствуетесь 250 тысячами записей в секунду и вам хватает миллиона серий, вам вполне будет достаточно машины с шестью ядрами и 32 ГБ оперативки в пределе. Это такой средний сервачок. Если же вам нужны более лояльные условия, железо там будет совсем смешным. Мы в своих проектах для многих своих Influx-ов даже не выделяем отдельного сервера, потому что он не влияет на продакшн нашей системы почти никак, мы прямо там его и запускаем.
Помните идею хранить time series в обычной базе данных? Давайте посмотрим, что из этого может получиться:
В левом углу ринга типичные представители TSDB — это InfluxDB и OpenTSDB. OpenTSDB — это вторая по популярности TSDB, поэтому она попала в этот тест.
В правом — типичные представители документоориентированных БД.
У вас, конечно же, может возникнуть резонанс, что не очень честно сравнивать документоориентированные БД, со всей их мощностью, с узкоспециализированными хранилищами. Тем не менее, такое сравнение имеет смысл, потому что на практике для временных рядов люди часто используют именно такие БД. И хотелось бы показать, что у разработчиков может получиться, если они перейдут на специализированные средства.
От elastic отключены все дополнительные функции (индексирование, поиск и так далее), чтобы максимально сблизить его с конкурентами.
Итак, запись. На запись Influx рвет всех от 5 до 27 раз:
Сжатие данных удается ему от 9 до 84 раз лучше, чем всем остальным:
На чтении он примерно сравним с MongoDB, что по факту означает в 168 раз быстрее Cassandra.
Не говоря об отвратительном синтаксисе запросов и нетривиальном способе установки у многих его конкурентов.
Как мы видим, Influx очень хорошо справляется с поставленной ему задачей. Посмотрим, как он поможет писать метрики вашего приложения. Есть такой замечательный пакет, который называется App Metrics, создан для того, чтобы легко и быстро снять метрики с ваших WebAPI-контроллеров, записать их в БД и визуализировать в Grafana. Давайте посмотрим, как это происходит:
Итак, типичное Owin-приложений, здесь нет ничего нестандартного, всё ожидаемо, кроме двух строчек, которые я оставил, это использование App Metrics:
И, в конфигурации сервиса, использование InfluxDB для записи метрик туда:
Здесь есть интересная секция, HealthChecks:
HealthChecks — это маленькие «проверяльщики» сторонних сервисов, от которых может зависеть ваше приложение. Дальше мы посмотрим на графиках, как они выглядят.
Я запускаю сервер, у меня также есть клиент, который атакует мой сервис запросами, чтобы мы увидели какие-то хорошие графики:
На сайте AppMetrics вы почитайте, что он может, как его устанавливать, как настраивать, я не буду на этом останавливаться.
Перейдем непосредственно к дашборду.
Как и у всех других, у него есть уникальный номер, который мы копируем к себе, выбираем источник данных, и через секунду у нас появляется полная информация о наших API-контроллерах:
Пропускная способность, количество ошибок, разбитых по контроллерам, по типу эксепшнов, по коду возвратов, пропускная способность по каждой точке, по каждому роутингу в вашем приложении. Здесь вы очень легко можете посмотреть, какие точки отдают данные быстро, какие — медленно и так далее. Вот, кстати, наши HealthCheckers:
Они показывают, что некоторые сервисы доступны из нашего приложения, а некоторые — нет.
Перед вами, конечно же, может стоять жестокий выбор, какие графики использовать, какие метрики нужно собирать и так далее. Какие метрики нужно внедрить в наше приложение в первую очередь, чтобы получить максимальный эффект от всего этого? У меня есть небольшой алгоритм:
- Во-первых, установите Telegraf и дашборд, как в первом демо. Это поможет вам собирать основные характеристики вашего железа и операционной системы.
- Установите App Metrics и дашборд, как во втором демо. Наверняка у многих из вас есть Web API, и вы без труда сможете это сделать.
- Поиграйтесь с этим. Поживите с этим. Посмотрите на ваши графики, сравните, как изменяется нагрузка на процессор, когда к вам приходит запрос с большим body. Поменяйте цвета, попробуйте поменять местами графики, оптимизировать их порядок.
- Удалите все графики, которые вам не пригодились и которые вам больше не нужны.
- На этот момент у вас будет достаточно опыта, чтобы начать писать свои собственные графики, собственные метрики в БД и строить собственные графики на вашем бизнес-домене.
К сожалению, у меня нет дашборда, который подойдет для вашего бизнес-домена, который отобразит все ваши критически важные участки, этим вам придется заняться самим. Вы должны выяснить, какие метрики в вашем домене должны быть обязательно залогированы и отслежены. Я же могу вам показать то, каким образом вы можете писать в Influx и каким образом можно строить графики в Grafana.
Давайте опустимся на уровень ниже и посмотрим на примере, который мне поможет сделать замечательная библиотека BenchmarkDotNet. Итак, представьте мое бизнес-приложение: я пишу архиватор. Очень крутой архиватор, я добился шикарных значений, он сжимает просто блестяще. Я очень много экспериментирую с алгоритмами, и, чтобы эксперименты не вывели мой бизнес в трубу, я каждую ночь запускаю бенчмарк-тесты, которые все результаты моих измерений пишут в Influx. И каждое утро, когда я прихожу на работу, я открываю Grafana и вижу графики того, что я вчера натворил, улучшил или, наоборот, ухудшил.
Как это можно реализовать? В принципе, очень легко. Начнем знакомство мы с утилиты командной строки, которая называется influx.exe:
Она способна подключиться к любому серверу Influx и выполнить на нем произвольные запросы по выборке данных. Например, давайте создадим БД benchmarks, в которую мы будем писать результаты измерений.
Теперь перейдем к моему приложению: как я уже говорил, у меня есть два алгоритма, над которыми я сейчас работаю.
Есть быстрый алгоритм компрессии:
И медленный:
На них навешаны стандартные атрибуты BenchmarkDotNet, что позволяет мне запускать эти бенчмарки каждую ночь в автоматическом режиме. Единственный нестандартный атрибут, который здесь есть — это InfluxExporter, я его сам написал:
Он принимает в качестве параметра имя сервера и пишет туда значение. Он сделан вот так:
Он должен быть пронаследован от интерфейса IExporter, стандартного интерфейса BenchmarkDotNet, это нужно для того, чтобы получить результаты наших измерений от библиотеки.
Писать мы будем при помощи MetricsCollector:
Это класс, который находится в пакете InfluxDBCollector. Очень хороший пакет, он дает нам возможность расширить наши метрики.
Здесь я добавил имя хоста и где производилось измерение. Ещё он может упаковать наши метрики в батчи, чтобы мы отсылали данные раз в секунду, а не в real time.
И, непосредственно, измерение:
Этот метод дергается бенчмарком.
В InfluxDB всё это записывается с помощью так называемого LineProtocol, который представляет собой обычный текстовый протокол вот в таком виде:
Здесь есть имя метрики, перечислены все теги и так далее.
Перейдем к Grafana. Чтобы начать ей пользоваться, нам необходимо создать Data Source.
Выбираем ему имя, ставим тип InfluxDB, адрес Influx и имя самой БД (которую мы создали в начале). Data Source готов, теперь мы можем строить дашборды на его основании.
У Influx есть множество типов графиков, я покажу всё на примере самого мощного и популярного.
Выбираем Data Source и видим, что Influx заполнил автоматически почти все поля. Выбираем то, что нас интересует, можем добавить еще один график и мгновенно получаем вот такую картину:
Здесь чётко видно, что у меня есть медленный и быстрый алгоритмы. И они работают почти стабильно на протяжении последнего времени. Что касается пиков на моих графиках: я долго не мог разобраться, что это такое, пока не подключил стандартный график из поставки Grafana с фазами луны.
Полнолуние очень сильно влияет на мои алгоритмы, это проблема, я ее обнаружил и хочу теперь настроить для нее алерты.
Переходим на вкладку с алертами и говорим, чтобы при достижении определенного значения Grafana отправляла мне уведомления в Telegram. И всё, этого достаточно.
Естественно, поддерживается много других интересных выхлопов, кроме Telegram. И к вам придут не просто невнятные цифры, у вас будет красивая фотография вашего графика с проблемным местом и множеством другой полезной информации. Очень мощная и интересная вещь.
Подробнее исходный код примера можно посмотреть в репозитории.
Итак, давайте подводить итоги.
Метрики имеют много преимуществ перед логированием. Они компактнее хранятся, очень легко визуализируются, идеальны для анализа, том числе и в реальном времени. Но с помощью них покрывается только небольшое подмножество требований. Поэтому логирование никуда не денется со своего пьедестала. Но, когда вы будете проектировать вашу систему мониторинга, старайтесь вынести в метрики как можно больше информации. Всё, что может быть представлено в виде временных рядов, должно ими стать. Всё остальное отдавайте логированию.
Безумно интересной секцией, когда вы работаете с временными рядами, являются именно алгоритмы. И это не только алгоритмы компрессии и хранения, которые мы разобрали, это еще и алгоритмы анализа, которые мы не затронули. Приведем один маленький пример.
Это алгоритм Dynamic Time Warping. Он способен находить похожие графики по форме сигнала. Естественно, «похожесть» он определяет не попиксельно. Ему по зубам не просто одинаковые кривые, но и примерно похожие, а также сдвинутые, растянутые, искаженные и т.д. Алгоритм часто применяется в распределенных системах для выявления первоначальной причины сбоя: например, у вас есть большой кластер, много микросервисов, и есть API gateway. На ваш API gateway начинается DDoS-атака. Соответственно, вся ваша система поднимается, начинает работать. Некоторые микросервисы могут отказать со 100% загрузкой CPU, некоторые — из-за большой очереди к диску, некоторые — из-за нехватки памяти. Вам, чтобы устранить эту проблему, необходимо обнаружить первоначальный источник, вы не можете бегать по всем микросервисам и диагностировать каждый из них. Вручную это сделать практически нереально. Но DTW способен найти связь между всеми этими метриками и выявить первоначальный источник проблем.
А теперь представьте, что у вас не распределенная сеть компьютеров и вычислительных систем, а распределенная система человеческих органов, работающая в сложном организме. Действительно, все алгоритмы те же самые, но результат, как вы понимаете, намного интереснее и намного важнее. И да, пульс, дыхание, пищеварение, давление — всё это тоже временные ряды.
Ваш голос — тоже временной ряд. Здесь применяются алгоритмы по распознаванию и синтезированию голоса.
Еще существует интересная работа по траектории движения пьяного водителя.
Оказывается, это тоже временной ряд. Анализируя этот график, вполне можно предсказать возможность аварии и заранее предупредить печальные исходы. Самое интересное, что весь этот анализ происходит на мобильном устройстве самого водителя.
Давайте спустимся к нашим реалиям и рассмотрим инструменты. Компания InfluxData предоставляет вам набор из нескольких инструментов, которые могут помочь вам в вашем приложении. Все они объединены под общим названием TICK и отлично интегрируются друг с другом.
С Telegraf мы уже знакомы. Это коллектор метрик, способный агрегировать данные и пересылать их на сервер.
InfluxDB. В принципе, InfluxDB прекрасен, его бесплатной версии должно хватить, если вы делаете менее миллиона записей в секунду. Единственное существенное ограничение бесплатной версии — это отсутствие кластеринга. Поэтому, если вам нужна отказоустойчивость и надежность системы метрик, вам необходима платная версия, где всё это есть. Influx продается как в облачном решении, так и self-hosted.
Chronograph — это веб UI, который должен объединить всё это семейство. Он ужасен, поэтому я о нем не рассказывал. Но, к сожалению, другого инструмента у нас нет. Если вам нужно просто зайти в Influx и посмотреть, какие там есть данные, какие созданы метрики, какие есть retention policy, то это безобразие вам поможет. Он, в принципе, хорошо развивается, есть надежда, что в ближайшем будущем им даже возможно будет пользоваться.
Kapacitor позиционируется как средство для детекта аномалий с помощью машинного обучения. Но у него очень много багов и мозговыносящий синтаксис запросов, поэтомфу пользоваться им на практике совершенно нереально в ближайшие годы, даже не пытайтесь. Если вам действительно нужно будет детектить аномалии с помощью машинного обучения, работает следующая связка: вы точно так же храните данные в Influx, но читаете их при помощи собственного приложения, которое вы пишете с учетом имеющегося домена, и в качестве анализаторов используете стандартные библиотеки для машинного обучения. Вот это прекрасно работает. Если вам нужно, смотрите в эту сторону.
Если конкурента Influx еще как-то можно подыскать, то Grafana вне конкуренции. Великолепные визуализации, минимальное количество багов. Наличие визуального редактора запросов, делающего порог вхождения плоским. Гибкая система плагинов, обеспечивающая существование: кучи источников данных, нестандартных панелей и готовых дашбордов под все популярные нужды. Это единственное веб-приложение отзывчивость которого не вызывает у меня желание разбить стулом монитор. В общем, тут даже не пытайтесь искать альтернативу в ближайшие годы.
Интересен такой момент в связке Grafana и Influx: эта схема является довольно-таки автономной. Что это значит? После того, как вы установили эти инструменты, вы даете разработчику всего два URL. Первый — от Influx, и разработчик, реализуя очередную фичу, начинает писать в этот URL собственные метрики. Ему ничего не нужно знать об Influx, потому что там динамическая схема, Influx сам подстроится под нее. Второй URL — от Grafana. Разработчик записал данные в Influx, заходит в Grafana, и, с помощью визуального редактора, легко и быстро накликивает себе приятные графики, сразу видит результаты своей непосредственной работы, а это очень важно в практике разработки. Таким образом происходит очень большое покрытие метриками вашего приложения, которое в будущем может очень хорошо сыграть вам на руку.
К сожалению, очень много инструментов в современном мире выпускается с Linux-first подходом. Это значит, что, прежде всего, программа разрабатывается под Linux, а потом переносится по остаточному принципу на Windows. Такая же участь постигла и наших героев. Grafana легче, у нее веб-интерфейс, ей все равно, где запускаться, а вот Influx, несмотря на то, что разрабатывается уже более пяти лет, получил дистрибутив под Windows только полгода назад (я еще из тех старперов, кто собирал его из исходников). На данный момент единственное, что осталось от такой наследственности, — это то, что данные инструменты представляют собой консольные приложения и не умеют запускаться в виде Windows-сервисов, что является стандартной единицей деплоя на наших Windows-системах. Эту проблему вам поможет решить такой инструмент, как NS Service Manager, он берет консольное приложение и делает из него полноценный Windows-сервис. Маленькая и хорошая утилита, работает без перебоев и нареканий.
Давайте посмотрим на альтернативные подходы. Итак:
- если вам не важны мгновенная вставка и быстрое чтение;
- если вы не упираетесь в пропускную способность;
- если вы не мечтаете о прозрачном downsampling’е;
- если вы не знаете как вам могут помочь Continuous Queries;
- если вам не нужны встроенные функции статистики и расширенной агрегации;
- если вы хотите лично удалять каждую устаревшую запись;
- если вас не пугает размер базы;
- если вы уверены в отсутствии высоких нагрузок на вашу систему;
- если вы готовы лишиться анализа в реальном времени.
То вы, в принципе, можете использовать стандартные базы данных для того, чтобы сохранять в них метрики. И это не так смешно, как кажется на первый взгляд, потому что готовая экспертиза в команде, которая уже работала с этими старпёрами, может превысить тот порог риска, который необходим, чтобы втаскивать в ваш проект какие-то новые инструменты.
Я встречал много проектов, для которых этот способ оказывался самым жизнеспособным, поэтому не стесняйтесь, это нормально, это бывает.
Та связка, которую я вам сегодня показывал (Telegraf, Influx и Grafana) — это наиболее низкоуровневая, наиболее оптимальная по производительности и гибкости система. Естественно, не всем нужен такой низкий уровень. Многие не хотят над этим заморачиваться и хотят выбирать более высокоуровневые решения, их тоже на рынке полно, они тоже работают, и они тоже могут вам подойти, пробуйте.
Также, если вы не стесняетесь облаков, есть куча платных решений, довольно хороших.
Обычно все эти высокоуровневые решения работают и с метриками, и с логами вместе, чтобы попытаться скоррелировать их в одну схему, одни дашборды.
К сожалению, нельзя рекомендовать что-то одно. Когда мы говорим о высокоуровневых решениях, нужно смотреть конкретно на ваш проект, на ваши нагрузки, на ваш подход к разработке. InfluxDB и Grafana являются неким базовым уровнем, на который вы должны ориентироваться, если вдруг решитесь на поиск альтернатив.
Как вы, наверное, заметили, одна из отличных возможностей при работе с TSDB — это знакомство с их алгоритмами. Алгоритмы довольно интересные:
- Gorilla Paper
- Akumuli
- Run-length encoding
- Varints
- ZigZag
- Dynamic time warping
- Sketch-based change detection
- Mobile Phone Based Drunk driving detection
Вот ссылки, которые помогут вам немного вникнуть в эту тему. Если вы вдруг фанат какой-нибудь битовой магии, элегантных решений или просто классного и хорошего сжатия, почитайте этот минимум на ночь перед сном, я думаю, вам хорошо будет спаться.
Если мы хотим ознакомиться с подробной информацией о наших героях, для этого достаточно стандартной информации на их официальном сайте:
Она очень хорошо написана, естественно, всегда актуальна.
Если после прочтения статьи у вас будут вопросы, смело пишите мне о том, как вы используете метрики, о том, какие интересные графики у вас есть:
Я этой темой буду заниматься еще долго и много, потому что, как сказал классик: «Оптимизм — это недостаток информации». Поэтому, друзья, будьте реалистами, знайте, что делает ваше приложение. Спасибо за внимание.
Минутка рекламы. Как вы, наверное, знаете, мы делаем конференции. Ближайшая конференция по .NET — DotNext 2018 Piter. Она пройдет 22-23 апреля 2018 года в Санкт-Петербурге. Какие доклады там бывают — можно посмотреть в нашем архиве на YouTube. На конференции можно будет вживую пообщаться с докладчиками и лучшими экспертами по .NET в специальных дискуссионных зонах после каждого доклада. Короче, заходите, мы вас ждём.
Автор: Олег Чирухин