Fork me on GitHub

Отчет об участии в DjangoDash

Django Dash это небольшое соревнование для django-программистов-фанатиков, суть которого сводится к реализации небольшого проекта в течение двух выходных дней. Точнее двух суток. Т.е. в абсолютно сумасшедшем режиме. В этом году я учавствовал с коллегой Юрой и мы пытались сделать сервер для мониторинга gearman очередей (очень гиковская задумка). О том как все это прошло и чем завершилось, see below.

Intro

В первую очередь хочу сказать огромное спасибо компании Grammarly, которая в этом году "приютила" 3 киевские команды. Большое спасибо за очаровательный уютный офис, изумительно вкусные обеды и хорошую компанию таких же фанатиков как мы :)!.

Что нами задумывалось изначально?

Итак, нашей идеей было создать приложение Gearoscope, суть которого сводилась к мониторингу Gearman серверов на удаленных машинах: проверка состояний очередей и отслеживание процессов, которые занимаются выполнением задач из этих очередей. Задумка достаточно дерзкая, но исключительно полезная. У меня в проекте, который я делаю на работе (делал), одна gearman-нода обслуживает 7 очередей и около 200.000 task-ов в них за сутки. И это достаточно простая ситуация, можно все контролировать вручную, хотя "телодвижений" для этого уже приходится совершать очень и очень немало. Если же взять кластер побольше, то там и подавно можно потеряться.

Как разработчику, или администратору системы, мне интересны следующие вещи:

  • какие у меня есть gearman node-ы и доступны ли они в данный момент

  • какие очереди "висят" в памяти, сколько там задач сейчас и какая динамика наполнения (задачи "прибывают" или "убывают" - это важно для принятия решения о небходимости увеличения workers capacity)

  • что творится с worker-ами - процессами, которые эти задачи выполняют: сколько их, на каких машинах они крутятся, сколько памяти и CPU используют и т.д.

Помимо чисто мониторинговых задач позже сюда добавились требования:

  • поднять новую ноду на удаленной машине

  • запускать и перезапускать воркеры (как в ручном режиме, так и по автоматизированным сигналам)

  • читать логи мониторинг системы и воркеров

  • другое

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

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

  1. Монитор-сервер и визуализатор данных разделены не только идеологически, но и программно. Т.е. один процесс пишет все происходящее в логи, другой это логи читает, анализирует и визуализирует.

  2. Монитор-сервер должен быть один, никакого дополнительного программного обеспечения не нужно устанавливать на каждый сервер в кластере. Прототип такой штуки у меня уже был и использовался в рабочем проекте. Для того, чтобы не нарушать условия соревнования, но и не писать заново то, что уже есть, я перепил прототип и буквально за день до начала соревнования выложил фрейм как открытый проект Sonar. В его основу положена мультиагентная архитектура, которая дает возможность выполнять различиные действия переодически в thread-ах или пулах thread-ов, забирая задачи из синхронизируемой очереди. Мини-фреймворк устанавливается через pip и имеет широкие возможности конфигурирования и "встраивания" в основной loop "сторонних" агентов.

  3. Управление процессами достаточно сложная задумка, поэтому было решено использовать supervisor для запуска под ним воркеров. Это не только удобный способ внешней демонизации, но и XML-RPC интерфейс для получения детализированной информации о статусе процессов, а также удаленном их старте/рестарте/остановки.

  4. Чего не умеет supervisor, так это отдавать инфу об использовании mem, cpu. Для того, чтобы закрыть этот пробел решили на локальной машине использовать библиотеку psutil, а для работы на удаленных - fabric + ps aux + немного уличной магии.

  5. Async I/O. В крупном кластере, монитор-сервер может получать большое количество информации. Чтобы постоянно не дергать лог, пытаясь в него что-то писать, было решено писать данные в memory buffer, и уже его переодически дампить в файл "большим" куском.

  6. Визуализатор делится на две части: dashboard с графиками и HTML5 версткой (спасибо Юре) делающий ajax запросы на log analyzer, Django админка для управления всеми объектами в приложении (спасибо мне).

  7. Pip иснталлятор для быстрого разворачивания приложения.

  8. Soft-reload при изменении конфигурации. При изменении конфигурационного файла внешними средствами, монитор должен аккуратно остановить все thread-ы и пересоздать всех агентов по новой конфигурации (основной процесс при этом не должен пострадать).

Составленная в субботу утром схема приложения:

Scheme

Как все пошло

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

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

Во-вторых, чем дальше к концу соревнования, тем я больше понимал, что разделение системы на две части было не совсем удачным решением. Sonar конфигурировался с помощью передаваемой в него фабрики (это удобно, просто в проекте мы сделали свою фабрику и передавали ее в установленный пакет). Но при этом он использовал для большей части объектов, агентов и пулов конфигурационный файл специального формата. Поэтому достаточно много времени я потратил на то, что при внесении изменений в базу в веб-интерфейсе, перерендеривался конфигурационный файл (Sonar должен был сам на это реагировать и делать soft reload). Для такой задачи очень удобными оказались post_save сигналы, которые перехватывались специальными хендлерами... Но основной проблемы это все равно не исправило и забрало много времени.

Позже, я начал частично переносить конфигурацию в settings.py, а sonar запускался уже не как отдельный демон, а через django command interface

python manage.py startsonar

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

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

Следующая проблема заключалась в том, что данных было очень много и формат их представления в логах был текстовым и неудачным для "разбора". С анализатором логов и рендерингом графиков работал Юра, и у нас много времени занимало обсуждения связей данных в единую "красивую" картину under-monitoring world.

Очень приблизительная схема связей в данных:

Data structure

Последним приключением стал деплоймент, который мы незаслужено отложили "на потом" (т.е. на 2 часа ночи). Я уже молчу о возне больше часа в nginx, от которого никогда проблем не ждали. Но это дело непредсказуемое. А вот ошибкой подготовки было то, что мы проектировали gearoscope как средство для "личного пользования". Чтобы посмотреть на логи монитора у себя на сервере, достаточно было возможностей встроенного runserver. Но ведь нам нужно "показать" демо-приложение судьям и "зрителям"... Поэтому мне пришлось в очень скором режиме прикручивать к системе gunicorn.

Что получилось по итогам двух дней (точнее двух суток) работы?

Огромное количество впечатлений, эмоций и драйва. И неплохой костяк для создания приложения. Не могу назвать это приложением, потому что до production-mode ему еще очень далеко. Не только с технической точки зрения, но и с точки зрения полезности/удобности и других плюшек, за которые такие приложения ценят. Смело могу сделать вывод, что иногда очень полезно работать в таком режиме, как минимум для встряски мозга, который очень быстро привыкает работать в "штатном" режиме и не напрягаться дольше 8ми рабочих часов в день.

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

Также могу констатировать, что наша команда попала в первую десятку рейтинга по количеству коммитов, а я занял почетное 3е место в Individual commit leaderboard с показателем в 147 коммитов за 2 дня. Спорное, но все же достижение :)

Следующий Django Dash

Если Djagno Dash будет проводится в следующем году, то обязательно поучаствуем, но с некоторыми "правками":

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

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

  • каким бы безумием это не казалось, но нужен какой-то Continious Integration, или его подобие, хотя бы. Ни в коем случае не допустимо выкатыватся на прод-сервер за 2-3 часа до окончания соревнований, потому что этот процесс всега стыкуется с чем-то непредвиденным. А начиная с первого "удачного" деплоймента нужно быть всегда уверенным, что после внесенных изменений можно в одну команду вернутся к предыдущей версии развертки, чтобы какая-нибудь критичная бага не застала в самый неприятный момент "финального свистка"

Планы по развитию проекта

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


CODE MEHANIKA

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

Алексей Качаев

Главный механик
Энергичный программист-фанатик
Senior Software Engineer
Zend Framework Contributor
Верю в TDD и Domain-Driven Design
Искренне люблю Python, CoffeeScript и Git

Контакты

kachayev#gmail.com
@kachayev
Code on Github
LinkedIn profile
Facebook