Intro
В первую очередь хочу сказать огромное спасибо компании Grammarly, которая в этом году "приютила" 3 киевские команды. Большое спасибо за очаровательный уютный офис, изумительно вкусные обеды и хорошую компанию таких же фанатиков как мы :)!.
Что нами задумывалось изначально?
Итак, нашей идеей было создать приложение Gearoscope, суть которого сводилась к мониторингу Gearman серверов на удаленных машинах: проверка состояний очередей и отслеживание процессов, которые занимаются выполнением задач из этих очередей. Задумка достаточно дерзкая, но исключительно полезная. У меня в проекте, который я делаю на работе (делал), одна gearman-нода обслуживает 7 очередей и около 200.000 task-ов в них за сутки. И это достаточно простая ситуация, можно все контролировать вручную, хотя "телодвижений" для этого уже приходится совершать очень и очень немало. Если же взять кластер побольше, то там и подавно можно потеряться.
Как разработчику, или администратору системы, мне интересны следующие вещи:
-
какие у меня есть gearman node-ы и доступны ли они в данный момент
-
какие очереди "висят" в памяти, сколько там задач сейчас и какая динамика наполнения (задачи "прибывают" или "убывают" - это важно для принятия решения о небходимости увеличения workers capacity)
-
что творится с worker-ами - процессами, которые эти задачи выполняют: сколько их, на каких машинах они крутятся, сколько памяти и CPU используют и т.д.
Помимо чисто мониторинговых задач позже сюда добавились требования:
-
поднять новую ноду на удаленной машине
-
запускать и перезапускать воркеры (как в ручном режиме, так и по автоматизированным сигналам)
-
читать логи мониторинг системы и воркеров
-
другое
Естественные требования к реализации: удобная админка для управления все этим делом, наглядный и юзабельный dashboard, позволяющий быстро охватить взглядом довольно большой объем информации, легкое разворачивание системы на существующем кластере, непритязательность к системным ресурсам для обеспечения работы самой мониторинг системы.
Задумка в реализации была основана на почти классических идеях организации мониторинг систем:
-
Монитор-сервер и визуализатор данных разделены не только идеологически, но и программно. Т.е. один процесс пишет все происходящее в логи, другой это логи читает, анализирует и визуализирует.
-
Монитор-сервер должен быть один, никакого дополнительного программного обеспечения не нужно устанавливать на каждый сервер в кластере. Прототип такой штуки у меня уже был и использовался в рабочем проекте. Для того, чтобы не нарушать условия соревнования, но и не писать заново то, что уже есть, я перепил прототип и буквально за день до начала соревнования выложил фрейм как открытый проект Sonar. В его основу положена мультиагентная архитектура, которая дает возможность выполнять различиные действия переодически в thread-ах или пулах thread-ов, забирая задачи из синхронизируемой очереди. Мини-фреймворк устанавливается через
pipи имеет широкие возможности конфигурирования и "встраивания" в основной loop "сторонних" агентов. -
Управление процессами достаточно сложная задумка, поэтому было решено использовать supervisor для запуска под ним воркеров. Это не только удобный способ внешней демонизации, но и XML-RPC интерфейс для получения детализированной информации о статусе процессов, а также удаленном их старте/рестарте/остановки.
-
Чего не умеет supervisor, так это отдавать инфу об использовании mem, cpu. Для того, чтобы закрыть этот пробел решили на локальной машине использовать библиотеку psutil, а для работы на удаленных - fabric +
ps aux+ немного уличной магии. -
Async I/O. В крупном кластере, монитор-сервер может получать большое количество информации. Чтобы постоянно не дергать лог, пытаясь в него что-то писать, было решено писать данные в memory buffer, и уже его переодически дампить в файл "большим" куском.
-
Визуализатор делится на две части: dashboard с графиками и HTML5 версткой (спасибо Юре) делающий ajax запросы на log analyzer, Django админка для управления всеми объектами в приложении (спасибо мне).
-
Pipиснталлятор для быстрого разворачивания приложения. -
Soft-reload при изменении конфигурации. При изменении конфигурационного файла внешними средствами, монитор должен аккуратно остановить все thread-ы и пересоздать всех агентов по новой конфигурации (основной процесс при этом не должен пострадать).
Составленная в субботу утром схема приложения:

Как все пошло
Раз уж я написал такой заголок, то вы догадались - пошло все немного не так, как планировалось. С какими проблемами мы столкнулись?
Во-первых, чтобы проект можно было "показать" публике, нужно было создать monitoring environment - т.е. совокупность работающих нод, генераторов заданий в очереди и воркеров их обслуживающих, которые бы постоянно функционировали в фоновом режиме и имитировали загруженность системы. На разработку этой штуки я потратил половину субботы.
Во-вторых, чем дальше к концу соревнования, тем я больше понимал, что разделение системы на две части было не совсем удачным решением. Sonar конфигурировался с помощью передаваемой в него фабрики (это удобно, просто в проекте мы сделали свою фабрику и передавали ее в установленный пакет). Но при этом он использовал для большей части объектов, агентов и пулов конфигурационный файл специального формата. Поэтому достаточно много времени я потратил на то, что при внесении изменений в базу в веб-интерфейсе, перерендеривался конфигурационный файл (Sonar должен был сам на это реагировать и делать soft reload). Для такой задачи очень удобными оказались post_save сигналы, которые перехватывались специальными хендлерами... Но основной проблемы это все равно не исправило и забрало много времени.
Позже, я начал частично переносить конфигурацию в settings.py, а sonar запускался уже не как отдельный демон, а через django command interface
python manage.py startsonar
На самом деле, до этого нужно было додуматся сразу, сэкономил бы себе кучу времени и нервов.
Sonar раньше нигде не проходил проверки как "фрейморк", поэтому повылазило много неудобств, нестыков и багов. Их приходилось фиксить "на лету", поэтому всю субботу я на скорую руку коммитил код в два проекта.
Следующая проблема заключалась в том, что данных было очень много и формат их представления в логах был текстовым и неудачным для "разбора". С анализатором логов и рендерингом графиков работал Юра, и у нас много времени занимало обсуждения связей данных в единую "красивую" картину under-monitoring world.
Очень приблизительная схема связей в данных:

Последним приключением стал деплоймент, который мы незаслужено отложили "на потом" (т.е. на 2 часа ночи). Я уже молчу о возне больше часа в nginx, от которого никогда проблем не ждали. Но это дело непредсказуемое. А вот ошибкой подготовки было то, что мы проектировали gearoscope как средство для "личного пользования". Чтобы посмотреть на логи монитора у себя на сервере, достаточно было возможностей встроенного runserver. Но ведь нам нужно "показать" демо-приложение судьям и "зрителям"... Поэтому мне пришлось в очень скором режиме прикручивать к системе gunicorn.
Что получилось по итогам двух дней (точнее двух суток) работы?
Огромное количество впечатлений, эмоций и драйва. И неплохой костяк для создания приложения. Не могу назвать это приложением, потому что до production-mode ему еще очень далеко. Не только с технической точки зрения, но и с точки зрения полезности/удобности и других плюшек, за которые такие приложения ценят. Смело могу сделать вывод, что иногда очень полезно работать в таком режиме, как минимум для встряски мозга, который очень быстро привыкает работать в "штатном" режиме и не напрягаться дольше 8ми рабочих часов в день.
Несмотря на то, что мы не успели сделать все, что хотели - мы, по крайней мере, четко осознали что же мы хотим от этого продукта и каким видем его будущее.
Также могу констатировать, что наша команда попала в первую десятку рейтинга по количеству коммитов, а я занял почетное 3е место в Individual commit leaderboard с показателем в 147 коммитов за 2 дня. Спорное, но все же достижение :)
Следующий Django Dash
Если Djagno Dash будет проводится в следующем году, то обязательно поучаствуем, но с некоторыми "правками":
-
менее гиковский проект, менее технически сложный и более близкий к "конечному" потребителю. Дай бог с идеями проблем не должно быть
-
проектирование нужно проводить до самых тонких мелочей до начала соревнования, потом на них просто не хватает времени
-
каким бы безумием это не казалось, но нужен какой-то Continious Integration, или его подобие, хотя бы. Ни в коем случае не допустимо выкатыватся на прод-сервер за 2-3 часа до окончания соревнований, потому что этот процесс всега стыкуется с чем-то непредвиденным. А начиная с первого "удачного" деплоймента нужно быть всегда уверенным, что после внесенных изменений можно в одну команду вернутся к предыдущей версии развертки, чтобы какая-нибудь критичная бага не застала в самый неприятный момент "финального свистка"
Планы по развитию проекта
Gearoscope будет развиватся дальше. После рефакторинга того, что уже есть сейчас, - мы перейдем к внедрению новых фич и налаживаюнию простого интерактивного процесса взаимодействия с монитором (об основных вехах и планах можно почитать в README на гитхабе, я не буду дублировать эту информацию здесь). Все, кто заинтересован в развитии или имеет пожелания/идеи/советы - пишите, форкайте и комитьте! Мы только за.
⇒ Особенности и примеры скриптов для Custom Keyboard Shortcuts
⇐ Моделирование данных и возможности Redis хранилища