Наверх ▲

Мониторинг как высоконагруженный проект

Александр Быков Александр Быков Старший программист в Yandex, Москва.
View more presentations from rit2010.

Александр Быков: Здравствуйте! Меня зовут Александр Быков. Я хочу рассказать о модификации мониторинга в Mail.ru в соответствии с ростом парка серверов нашей компании и о масштабировании решения.

Зачем вообще нужен мониторинг?

  • В первую очередь - для контроля работоспособности системы. Мы имеем большую систему, которую невозможно проверять вручную. Если из 2000 серверов один выйдет из строя, мы никогда не узнаем об этом. Мы даже не уверены, знаем ли мы обо всех своих серверах. При подобных масштабах нам просто необходима автоматическая проверка работоспособности оборудования.
  • Нам требуется контролировать некие минимальные параметры. Грубо говоря, web-сервер отдает статику. Мы периодически дергаем какую-либо картинку и проверяем, что отдает сервер.
    Самые простые проверки — на сам факт работы. Без этого никуда. Когда у вас несколько сотен Front end, вы их не проверяете, то у вас некоторым пользователям может быть плохо.
  • Следующий важный момент — локализация неполадок. Допустим, мы знаем, что у нас появилась проблема. Где? Есть 2000 серверов, давайте искать. Мониторинг должен указывать, где возникла проблема.
  • Дальше мы переходим к качеству сервиса. Нам нужно не только контролировать ошибки, которые имеют место здесь и сейчас, но и анализировать ошибки, допущенных ранее.
    В очередной раз у нас появляется известная проблема. Мы хотим посмотреть, сколько подобных случаев было в нашей практике, нет ли закономерности и что можно предпринять, чтобы улучшить качество сервиса. 
  • Пункт «Предупреждение и профилактика отказов». Мы анализируем, почему мы "ложились" в прошлый раз, в чем причины и что можно сделать, чтобы подобного больше не повторилось.

Проиллюстрирую теорию конкретным примером. Серверов у нас более 2,5 тысяч. На каждом — десятки проверок. Используемые протоколы - более или менее стандартные.

У нас действует принцип: мы стараемся не плодить сущностей. Если возможно осуществлять мониторинг при помощи стандартного протокола (пусть даже с не очень большим функционалом), то мы стараемся использовать его, а не изобретать велосипед.

Когда мы занимались модификацией системы, у нас использовались достаточно простые проверки. Применялись пинги, передача данных по HTTP (при наличии web-сервера) и выполнялось достаточно большое количество разных проверок по SNMP.

Наша специфика — почтовая. Почта SMTP, POP3 плюс проверка.

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

Расширение предполагало создание сложной сетевой структуры. дата-центры расположены в совершенно разных местах. Между ними функционирует довольно сложная структура каналов. Возникающие проблемы каналов связи диагностировать довольно сложно.

Следующая проблема - большая связь проектов друг с другом. Если вы зайдете, например, в проект «Почта», то увидите, информационные блоки с «Моего мира».

Кроме того, существует достаточно много площадок, что порождает большие сетевые эффекты. Когда на проекте «Мой мир» появляется какая-то проблема, это вполне может отразиться на почте.

На момент начала работ мы имели совершенно устаревшую систему мониторинга, которая не отвечала никаким требованиям.

Что нас не устраивает? 

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

Что требуется от новой системы?

  • Моментальное обнаружение проблем с сетью (в течение 20 секунд). В случае возникновения неполадок с каналом, мы желаем узнавать об этом достаточно оперативно.
  • Опрос базовых сервисов, например, HTTP. Если возникают проблемы с сервером по HTTP, мы хотим узнавать о них в ту же минуту, а не после "падения" некоторых сервисов. Место на дисках нам не обязательно проверять раз в минуту, т.к. оно не так быстро растет.
  • Высокую производительность. Что имеется в виду? Если взять Nagios, то на одном сервере он разместиться не сможет. Потребуется произвести его шардинг. Будет функционировать три-четыре сервера проверок, передающих информацию в единый сервис интерфейса.
    Однако данный вариант нас не устравивает. Мониторинг не такая сложная задача, чтобы выделять для её выполнения отдельный кластер. Все вполне должно уместиться на один сервер и по трафику, и по ЦПУ.
  • Децентрализованность и работа при потере связности. Я говорил, это проблема с дата-центрами, их отключением, это потеря каналов и проблемы с сетью.
  • Дальше хочется, чтобы система не только осуществляла мониторинг, но и включалась в общую систему управления серверами. Где какие серверы, что на них стоит, что на них надо мониторить, какая версия ПО установлено. Тоже нужно осуществлять какое-то взаимодействие.
  • Очень хочется иметь интерфейс, в котором можно было бы работать и искать какие-то события. Когда большая система, вещей, которые нас интересуют одновременно, может быть достаточно много. Хочется из них выбирать что-то конкретное. Грубо говоря, проблемы, относящиеся к конкретному проекту, например. Администратор конкретного проекта смотрит свой проект. Хочется иметь группировки, фильтры.
  • История, графики — это все понятно.

Почему Nagios нас не устраивает?

  • Во-первых, его внутренняя архитектура: fork() на проверку — это непозволительно дорого. Сейчас fork() стал работать быстрее. Но лет 5 назад это все-таки было совсем неприятно.
  • Внутренняя архитектура рассчитана на проверку раз в 60 секунд. Там есть параметр, которую можно настроить, чтобы проверка проводилась чаще. Но они сами пишут, что это не тестировали. То есть настраивать проверку приделся на свой страх и риск. Естественно, нам это тоже не очень нужно.
  • Сложные и громоздкие файлы конфигурации. Даже те, что были у нас всегда, компактнее Nagios, наверное, раз в 10. Таким файлом пользоваться совершенно невозможно.
  • В силу того, что все проверки достраиваются на стороне мониторящего сервера, достаточно неудобно мониторить по SNMP. Каждый параметр SNMP нужно задавать отдельным exec.
    По SNMP мониторим много — это десятки проверок на машину. Получается, что мы должны десяток скриптов положить для одной конкретной машины.
    Нужно несколько десятков exec, чтобы мониторить каждый параметр раздельно. А в Nagios по умолчанию предлагается "сваливать" все проверки SNMP в одно сообщение. Это совершенно неприемлемо, потому что проблемы совершенно разные.
  • Nagios не умеет собираться... Непосредственно интерфейс отображений, та часть, которую будет видеть дежурный администратор, может работать только на одной машине. Он может с нескольких машин собирать проверки, но не умеет шардить, чтобы параллельно несколько работало.
  • Интерфейс нам совершенно не нравится.
  • Отсутствие СУБД очень не нравится, потому что мы не можем с помощью SQL "прикрутить" это к другим системам. Nagios "весь в себе". Чтобы подключить другую систему, надо писать кучу хаков. Это очень хлопотно.

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

У нас отдельные демоны проверки (англ. checker) для каждого типа проверки.

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

Нам достаточно в MySQL иметь таблицу, которую можно даже обычным select получить. В ней хранится весь список актуальных проблем. Положительные memcaсhed, которые нужны, чтобы понимать длительность проблемы, и прочее.

Интерфейс просто объединяет данные (англ. merge) из нескольких мониторингов. У нас есть несколько баз, в которых лежит список проблем. Мы просто выполняем слияние данных. Таким образом обеспечивается отказоустойчивость.

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

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

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

Хочется сказать немного о проверке высоконагруженной части. С базами разобрались. В Mail.Ru в основном используется язык Perl, поэтому логично подобные вещи писать на нем.

Приличный модуль для синхронной работы с сетью — это фреймворк AnyEvent. Это такая "обертка", которая позволяет работать с любым базовым уровнем обработки асинхронных событий. Обычно используется EV (ECT-шная библиотека либо EV), к ней "обертка" на Perl и уже поверх нее AnyEvent.

Это свежий модуль, он хорошо написан. Мы используем его. Уже существует масса модулей на основе AnyEvent. У него есть хороший модуль быстрой отправки PING, модуль для HTTP, поддержка технологии Socket.

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

Первая проблема. Допустим, мы мониторим 200 серверов front-end по одному и тому же URL. При асинхронной обработке логично, что в начале цикла мы берем и все их запрашиваем параллельно.

Тут возникает проблема. Оказывается, что мы, например, мониторим по одному URL одного и того же пользователя в «Моем мире». Мы получаем 300-500 запросов на одного пользователя в одну секунду (в одну единицу времени). В каком-то месте это может не очень быстро работать.

Получаются какие-то ложные срабатывания из-за того, что мы одновременно пытаемся получить доступ к одному и тому же ресурсу. Плюс еще пики по трафику могут быть. Поэтому приходится встраивать в эту систему некие алгоритмы «размазывания» запросов во времени. То есть мы запускаем не все запросы одновременно, а немного раскидываем их по времени.

То же самое касается PING. Когда мы берем и отправляем PING на все машины — это тоже плохо по сети проходит. Иногда начинают теряться пакеты, возникают проблемы. С использованием Socket проблем поменьше.

Еще есть проблемы с HTTP. По HTTP мы обычно стараемся мониторить страницу не по HEAD-запросам (которые запрашивают заголовок), а еще и BODY получать. Вдруг у нас BODY не отдастся? Мы идем на главную страницу и смотрим, что как отдается.

Например, для «Мира» это будет страница с профилем пользователя. Мы хотим получить всю страницу целиком, потому что сервер может отдавать HEAD-запрос, но при этом "тормозить" на выдаче BODY.

Мы хотим, чтобы он отдавал нам весь текст страницы за какое-то время. Страница большая, несколько десятков килобайт. Когда мы опрашиваем несколько сотен (а то и тысяч) таких страниц, то у нас получается значительный трафик, который генерирует HTTP. Реально десятки мегабит, сотня точно будет.

Это тоже проблема, потому что такая нагрузка по сети уже становится заметной. Не говоря о том, что сервер по ЦПУ достаточно ощутимо загружен.

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

Есть ещё проблема — асинхронно сбрасывая данные в MySQL, приходится выносить сброс данных отдельно от основной проверки. Тоже не очень удобно программировать. Иначе блокирующие операции на базе вызывают ложное срабатывание, тайм-аут. Это асинхронный FSM, конечный автомат. Любые задержки влияют на общее время проверки.

Очень важный момент: при синхронной проверке сервиса важно отметить следующее. Нет никаких блокирующих вызовов как, например, в MySQL. Сервер всегда успевает, нет пиков по ЦПУ. Если, грубо говоря, сам мониторящий сервер начинает тормозить, то мы начинаем "продалбливать" проверки.

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

Я хотел бы остановиться на разных протоколах, которые представляют какой-то интерес, и рассказать, какие мы с ними были проблемы. Есть протокол SNMP. Его мало кто из системных администраторов знает и активно использует.

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

Плюсы

  • Одним из плюсов является возможность мониторинга сетевого оборудования. Если у вас коммутаторы, единственный протокол, по которому вы можете снять данные, — это SNMP. Все сетевые аппаратные серверы имеют SNMP. Можно получать кучу параметров типа трафика, флопов, и так далее. По SNMP отдается масса информации. Оборудование можно мониторить полностью по SNMP. Это очень удобно.
  • Для Linux есть SNMPD стандартный, который сразу позволяет мониторить множество рабочих параметров (диски, запущенные процессы, использование ресурсов ЦП и количество процессов в очереди на исполнение (англ. Load average)). Плюс там есть еще механизм exec, который позволяет делать настраиваемые проверки маленькими скриптами на серверах, что достаточно удобно.
  • У него есть всевозможные механизмы расширения. Можно сделать Perl, написать небольшой Perl-модуль, который реализует какое-то количество проверок.

Плюс можно реализовать отдельный агент (висящий на машине демон), взаимодействующий с основным сервером. Ни то, ни другое мы пока не проверяли, не пытались плотно эксплуатировать. Но возможность такая есть.

Какие есть проблемы у SNMP? Он всем замечательный, если бы не некоторые архитектурные проблемы и некоторые трудности в плане реализации.

Архитектурные проблемы

  • В SNMP практически невозможно (он так построен) получить параметр. Там все параметры сделаны итераторами. То есть если у вас есть проверка типа exec, они идут по номерам: проверка exec 1, проверка exec 20. 
    Единственный вариант получить все проверки по exec — это сканирование. Либо делать какие-то хитрые мультигеты, когда мы берем первые четыре параметра, потом следующие четыре параметра и ждем, пока они закончатся (то есть работать придется какими-то блоками). Нельзя сказать: «Дай мне все exec проверки, чтобы вернуть все ответы с exec». Это принципиальное ограничение протокола.
    Это подразумевается под необходимостью последовательного сканирования. Мы вынуждены каждый сервер сканировать последовательно сверху вниз. Берем, сканируем все exec, все диски, все процессы. Параллельно запускаем четыре потока. Все это в синхронном демоне, весь поток сканирования.
  • Небольшие возможности проверок. Количество проверок ограничено. Там есть не все. Например, нет CPU Usage (использование ресурсов ЦП в процентах). Есть только Load average. Многих проверок не хватает.
    Плюс он умеет только показать «есть проблема/нет проблемы». Например, мы мониторим диск по использованию. В SNMP проблема мониторинга на опросе появляется только тогда, когда диск уже переполнен, когда будет превышен нужный лимит. Нельзя получить его заранее или каким-то уровнем проверок.
  • Дальше начинаются истории с проблемой SNMPD, как он написан. В SNMPD замечательная совершенно вещь — доступ к exec полностью блокирующий. Когда один клиент пришел и выполнил exec, все остальные клиенты в этот момент ждут. Это очень неприятно. Exec приходится писать аккуратно и разносить их — на часть, которая работает в фоновом режиме, и часть, которая получает результат с какого-то файла.

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

 Здесь используется модуль SNMP::Multi. Он основан на базовом модуле use SNMP (net-snmp.org — стандартный SNMP-демон).

Библиотека очень странная. Во что мы уперлись моментально на первых тестах — внутри используется select для асинхронного опроса. Библиотека имеет асинхронный вызов.

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

Для нас скорость SNMP-опроса не так критична. Мы просто написали код так, чтобы он делал одновременно не больше 1000 проверок.

Каким-то образом эта библиотека умудряется "глючить". Периодически у нее появляются зависшие запросы. Мы говорим: «Вот тебе 1000 запросов. Опроси нам за 60 секунд. Если за 60 секунд не успеешь, верни нам по тайм-ауту».

Иногда, после нескольких часов работы, какие-то сервис-соединения не приходят. Мы запросили 1000 соединений, тайм-аут на все 60 секунд. По истечении 60 секунд два осталось, они не пришли. Какие-то совершенно странные внутренние проблемы. Если уменьшается 1000, например, на 500-700, то обычно становится нормально.

Это чужая библиотека, она глючит, и приходится что-то с этим делать. Проблема обнаружена. Можно перепускать проверку, это не очень страшно.

Проблема в том, что ничего другого нет. Нет других нормальных Access-клиентов для SNMP. Есть Perl-реализации (именно скриптовые языки). Но они по ЦПУ по образовательности не работают. Слишком большая нагрузка.

Еще есть замечательный механизм SNMP-inform. Мы его тоже пытались использовать (и используем). Теоретически это замечательный протокол, который позволяет уведомлять о событиях. То есть это пассивные проверки. Сама «железка» (например, от CISCO) или сам сервер в момент возникновения проблемы шлет пакет с проблемой на сервер мониторинга.

Там есть два механизма. Есть SNMP trap - негарантированная доставка, при которой осуществляется элементарная отправка пакета. Есть SNMP inform - гарантированная доставка, при которой клиентом отсылается уведомление и ожидается подтверждение доставки.

Но по некоторым причинам в имплементации SNMPD предпринимается всего три попытки запроса с интервалом в одну секунду. Если подтверждение получено не было, то дальнейших попыток не будет. Данное решение нельзя назвать удачным. Что мешало проводить проверки требуемое количество раз?

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

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

Что касается проблем реализации, то в CISCO с этим возникают определенные затруднения, не говоря уже о стандартном SNMPD, где настройка отсутствует вообще.

На самом SNMPD проверка проводится следующим образом. Она не осуществляется в момент появления проблемы на серверах (не на оборудовании). Проверки инициируются с определенной периодичностью, после чего отправляется пассивный check. Интервал проверок можно настроить на каждые 10 секунд - на все check.

Вопросы и ответы

Вопрос:
— Скажите, я правильно понял, что у вас при проведении мониторинга не используются архивные данных?
Александр Быков:
— Нет, неправильно. История - хранится. Мы просто поменяли формат истории. Архивные данные есть.
Вопрос:
— То есть я могу просмотреть, что происходило год назад?
Александр Быков:
— Да. Конечно, у нас бывают некоторые проблемы с сохранностью аналитики в форме графиков. Это связано с большими нагрузками. Но все данные о проблемах за последние несколько лет в наличии есть. Т.е. узнать, какие проблемы существовали год назад, можно.
Вопрос:
— Я не про проблемы. Меня интересует время ответа какого-либо сервиса.
Александр Быков:
— Нет, подобные данные мы не храним ввиду их большого объема.
Вопрос:
— У меня создалось впечатление, что данная система мониторинга — набор "костылей" вокруг библиотек. Система функционирует нормально?
Александр Быков:
— Да.
Вопрос:
— То есть "костыли" — это не очень страшно?
Александр Быков:
— К сожалению, такова жизнь. Когда библиотеки начинают использоваться по-максимуму, с ними возникают проблемы, которые приходится решать.
Система мониторинга работает достаточно хорошо. Правда, мы не используем его для больших и "тяжелых" проектов.
Компактность и простота для нас важнее, чем фунциональность. Лучше быстро написать и быстро переписать, чем разрабатывать систему неопределенно долгий срок, после истечения которого она, может быть, не заработает из-за ошибок в архитектуре.
Вопрос:
— У меня забавный вопрос. У каждого есть, наверное, система мониторинга. Как вы определяете, что она "упала"? Как минимум нужно две системы мониторинга: вторая необходима для наблюдения за первой.
Александр Быков:
— Очень просто. Сервера наблюдают за состоянием друг друга, поскольку связаны в единую сеть. Если начинают возникать проблемы с одним сервером, его сосед об этом сигнализирует. Вероятность "падения" сразу двух серверов не очень велика.
Вопрос:
— Сколько вы разрабатывали эту систему? Время критично?
Александр Быков:
— Мы разрабатывали ее потихоньку. Первая переписанная версия была создана приблизительно в течение месяца (была проведена большая часть проверок). На SNMP мы тоже потратили около месяца до тех пор, пока не довели ее до желаемого состояния.
Вопрос:
— Вы выбрали систему с опросами состояния различного оборудования и т.д. Почему не создали систему с агентами? Т.е. систему, при которой оборудование само портит соответствующие параметры при превышении определенных пределов.
Александр Быков:
— Вы заметили, наверное, что я достаточно подробно остановился на SNMP. Это по причине того, что мы используем SNMP в качестве упомянутого агента. Мы просто используем SNMP с некоторым количеством аккуратных exec, решая, таким образом, вопрос с агентом.
Если вопрос про PUSH, то используется SNMP inform (т.е. пассивные проверки). Это не отменяет активных проверок, т.к. полагаться только на пассивные не дальновидно.

Комментарии

Нет ни одного комментария

Только пользователи могут оставлять комментарии

Возможно, вам будет интересно:

Дмитрий Лазаренко

Дмитрий Лазаренко

Технический директор Российского подразделения Jelastic.

Дмитрий Лазаренко из команды Jelastic рассказывает об архитектуре и внутреннем устройстве данной платформы.

Владимир Габриелян

Владимир Габриелян

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

Интервью с Владимиром Габриеляном, техническим директором Mail.ru.

Илья Кантор

Илья Кантор

В JavaScript-разработке около 8 лет. Интересуют сложные Frontend'ы, обучение в области JavaScript и связанных технологий.

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