Инфраструктура и жизненный цикл разработки веб-проекта

в 20:00, , рубрики: python, Блог компании Mail.Ru Group, Веб-разработка, разработка, метки:

Когда проект маленький, особых проблем с ним не возникает. Список задач можно вести в текстовом файле (TODO), систему контроля версий, по большому счёту, можно и не использовать, для раскладки файлов на живой сервер их можно просто скопировать (cp/scp/rsync) в нужную директорию, а ошибки всегда можно посмотреть в лог-файле. Глупо было бы, например, для простенького сервиса с двумя скриптами и тремя посетителями в день поднимать полноценную систему управления конфигурациями серверов.

С ростом проекта требования растут. Становится неудобно держать в TODO-файле несколько десятков задач и багов: хочется приоритетов, комментариев, ссылок. Появляется необходимость в системе контроля версий, специальных скриптах/систем для раскладки кода на сервер, системе мониторинга. Ситуация усугубляется, когда над проектом работает несколько человек, а уж когда проект разрастается до нескольких серверов, появляется полноценная инфраструктура («комплекс взаимосвязанных обслуживающих структур или объектов, составляющих и/или обеспечивающих основу функционирования системы», Wikipedia).

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

Любая работа начинается с постановки задачи, будь то запланированная фича или сообщение об ошибке.

Управление проектами и задачами

В качестве системы «Issue & project tracking» мы, в Mail.ru, используем Atlassian Jira, которая является стандартом де-факто среди крупных организаций. Вот далеко не полный список компаний, использующих Jira: ru.wikipedia.org/wiki/Atlassian_JIRA. По функционалу, гибкости, расширяемости и удобству использования этой системе нет равных, и альтернативы я не вижу, хотя по имеющейся у меня информации некоторые крупнейшие IT-компании с тысячами сотрудников успешно (по их заверениям) используют Bugzilla в качестве багтрекера.

Для небольших команд и проектов целесообразнее использовать менее навороченные и более бесплатные аналоги вроде той же Bugzilla, Phabricator или Redmine. Как вариант, в случае использования хостинга проектов (GitHub, BitBucket и другие) можно использовать встроенные в них системы отслеживания ошибок.

На данный момент проект «Календарь» в Jira содержит 1816 задач, из которых 1386 успешно закрыты. Около 500 из них были багами =)

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

Система контроля версий

На сегодняшний день самыми распростанёнными системами контроля версий являются Git и Mercurial. Обе имеют, по большому счёту, схожий функционал (распределённые системы), хоть и различаются в деталях. Практически все проекты Mail.ru перешли на Git (кто с SVN, кто вообще с CVS), и Календарь — не исключение.

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

Весь код Календаря (frontend и backend) хранится в одном репозитории. Для небольшого и среднего проекта это позволяет быстро разворачивать весь проект целиком и легко отслеживать любые изменения в коде. Для больших и очень больших проектов (таких как Почта Mail.ru) более удобным представляется хранение клиентского и серверного кода в отдельных репозиториях (а то и нескольких), хотя, конечно, любой подход требует осмысленного и аргументированного решения.

На сегодняшний день у нас в репозитории Календаря 7175 коммитов, а за всё время было создано около 300 веток. Размер всего проекта 60 Мб.

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

Окружение для разработки

Говорят, что каждое правило в технике безопасности написано кровью. В IT-компаниях до такого, конечно, не доходит, но жёсткие правила, тем не менее, есть. Например, в Mail.ru только системные администраторы имеют доступ на «боевые» серверы и к данным реальных пользователей. Разработчикам доступны лишь тестовые машины с тестовыми пользователями, которая никак не связана с «живой», и вся разработка ведётся только в тестовой сети. Такое разделение обязанностей избавляет самых «умных» программистов от соблазна что-нибудь «быстренько поправить на живом» и заставляет более вдумчиво и качественно писать код.

Есть системы, которые очень трудно, а иногда и невозможно запустить на одной машине, например, Почта Mail.Ru: для полноценной работы ей требуется огромное количество библиотек, демонов, скриптов и сервисов. Такие проекты запускаются на нескольких (десятках) виртуальных серверов в тестовой сети, и разработчики работают с кодом, запущенным на этих машинах (vim, emacs, diff, вот это всё).

Нам в Календаре повезло: весь проект достаточно легко запускается на локальной машине разработчика и никаких проблем с разработкой нет. Для работы можно без ухищрений использовать любимые редакторы, IDE и отладчики, каждый программист работает со своим кодом и никак не влияет на работу других. Конечно, у нас тоже есть виртуальные серверы в девелоперской сети, но они используются, в основном, для тестирования. Ещё больше облегчает работу тот факт, что все в Календаре предпочитают использовать MacBook в своей работе, поэтому среда разработки практически не различается у членов команды.

Серверная часть календаря написана на Python, и, конечно же, мы используем virtualenv при разработке и развёртывании системы, поэтому для установки всех библиотек нужно всего лишь запустить команду

    pip install -r requirements/development.txt

из склонированного репозитория. Клиентская (фронтенд) часть использует npm и все зависимости ставятся так же легко и непринуждённо.

Сейчас в календаре используется 33 сторонние библиотеки Python.

Всё необходимое ПО на маке ставится из brew, и для первоначальной установки проекта на компьютер разработчика достаточно запустить

    brew install ...

со списком зависимостей. Конечно, одной команды недостаточно и потребуется дальнейшая настройка, например, инициализация пользователя и БД в PostgreSQL. В установке отдельных программ есть некоторые особенности (например, мы используем патченный nginx со своими модулями), но это не вызывает никаких проблем, потому что всё описано в системе документации (wiki).

Документация по проекту

Знание — сила. Знаниями стоит делиться со своими коллегами, их нужно записывать, чтобы не забыть самому. Идеальным местом для хранения информации являются wiki-системы, и в Mail.ru мы испольуем Atlassian Confluence в качестве таковой. Особых преимуществ перед другими wiki-системами у Confluence я не вижу (их функционал, по сути, схож), но так сложилось, что продукция Atlassian прижилась в нашей компании и пользуется популярностью. Хотя одно достоинство всё-таки есть: продукты одной компании легко интегрировать друг с другом, а в любой крупной компании все внутренние сервисы так или иначе связаны друг с другом.

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

В проекте Календарь в Confluence 122 страницы документации.

Любому продукту нужен контроль качества и наш Календарь не исключение.

Code review

Каждый разработчик сталкивается с ошибками в коде. Первый шаг в борьбе за качество — code review, это позволяет своевременно заметить любые огрехи в программе. Ещё одно достоинство аудита кода заключается в знакомстве с каждым коммитом как минимум двух программистов: того, кто написал код и того, кто его ревьюил (соответственно, ответственность так же делится пополам).

У Atlassian для code review есть шикарный инструмент Сrucible, но так исторически сложилось, что мы в Календаре используем Phabricator: open-source разработку от Facebook. У фабрикатора много возможностей, но мы используем лишь часть из них, а именно аудит, комментирование кода и просмотр репозитория онлайн.

В среднем, при каждом аудите коммита появляется три-четыре замечания.

После исправления замечаний коллег код проходит на следующие этапы контроля качества.

Синтаксический контроль и тестирование

Красивый код — хороший код. Следование правилам code-style всеми членами команды позволяет с первого взгляда разобраться в любом месте программы, а так же позволяет избежать подавляющего большинства глупых ошибок. Каждый пуш в репозиторий календаря проверяется с помощью PEP8, pyflake и pylint.

В календаре нет ни одного исключения из правил pep8 и pyflake.

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

На сегодняшний день у нас в проекте 580 автоматических тестов.

Для запуска различных задач мы используем open-source систему Jenkins CI (Continuous integration), в которой имеется три задания для календаря:

  1. для тестовых веток: синтаксический контроль (lint) кода, запуск всех тестов, подготовка отчёта code coverage
  2. для ветки prerelease: синтаксический контроль (lint) кода, запуск всех тестов, сборка тестового пакета (RPM) проекта и раскладка его на наш пререлизный (тестовый) сервер
  3. для ветки master: запуск тестов и сборка пакета (RPM) проекта

Все задачи запускаются при пуше соответствующей ветки по хуку в git-репозитории.

Сборка проекта длится, в среднем, около пяти минут.

Автоматическое тестирование — это хорошо, но человеческий ум и изобретательность бездушная машина заменить не в состоянии. На помощь приходят живые тестеры. Каждый релиз (а релиз проекта Календарь происходит, в среднем, раз в две недели) проверяется на пререлизном сервере нашими тестерами. Особое внимание они обращают на новый функционал, который был реализован за прошедшую неделю, а так же на тестирование критического функционала проекта.

На выходе получается один (или несколько, в зависимости от проекта) RPM-файл, который содержит в себе весь проект полностью, с virtualenv, всеми необходимыми зависимостями (библиотеками) и файлами (статикой).

Релиз собран, оттестирован, проверен и готов к выкладке на боевые машины, доступ к которым есть только у системных администраторов.

Раскладка проекта в бой

Админы — люди умные и ленивые. Если часто приходится делать рутинные операции, то почему бы их не автоматизировать?

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

Процесс выкладки новой итерации на живые серверы выглядит, например, так: админы, если нужно, правят файлы конфигурации проекта, прописывают необходимые версии RPM-пакетов и пушат изменения в репозиторий. Дальше всем занимается Puppet: все файлы конфигураций на всех серверах будут обновлены, пакеты установлены и нужные сервисы перезапущены.

Раскладка проекта занимает около одной минуты.

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

Логгирование ошибок

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

Система логгирования в Календаре настроена таким образом, чтобы отправлять все ошибки, исключения и просто варнинги в специальну систему под названием Sentry. В ней мы видим не только статистику по ошибкам (когда, какие ошибки и сколько раз возникали), но и подробнейшую информацию об этих ошибках: полный traceback (порядок вызова функций) со значением всех переменных в контексте каждой функции. Так же имеется информация о пользователе (email, ОС, браузер) и запросе (url, заголовки, GET и POST параметры). Все браузерные ошибки так же попадают в Sentry, правда, информация не столь подробна (JavaScript, ничего не поделаешь). Всё это позволяет легко локализовать проблемы и в кратчайшие сроки исправлять ошибки.

В основном, мы пишем в Sentry различные предупреждения. Например, в процессе рефакторинга, прежде чем отказаться от какой-нибудь функции мы всегда добавляем warning в неё, и только при отсутствии сообщений в Sentry, в следующую итерацию, эта функция будет окончательно удалена из кода. Бывают, конечно, и ошибки, бывает и много ошибок («факапы»).

В Sentry Календаря попадает, в среднем, около 100 сообщений в час. Sentry выдерживает тысячи ошибок в минуту (проверено на практике =).

Логгирование — хорошо, но этого недостаточно, проекту жизненно необходима статистика.

Статистика и графики

Статистику любят все. Менеджеры любуются ею, радуясь увеличению количества хитов и пользователей, разработчики получают информацию о «здоровье» проекта. Мы используем Graphite в качестве системы для сбора и хранения метрик, а так же StatsD — сервер, который обрабатывает и аггрегирует входящие метрики, передавая их на хранение во всё тот же графит.

Для чего нужны графики? Как я уже говорил, по графикам всегда можно судить о состоянии проекта: внезапно увеличилось количество редиректов, выросло в два раза среднее время запроса в базу или увеличилось количество операций ввода-вывода на одном из серверов. Всё это позволяет обнаружить проблему, а наличие истории (графики хранятся месяцами и годами) облегчают анализ внезапных неприятностей с проектом.

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

Графики показателей сервера (мы используем Diamond для этого) позволяют своевременно оценить нагрузку и заблаговременно заказать дополнительные машины или же озаботиться производительностью программ.

В графит Календаря каждую минуту пишется около 25 тысяч различных метрик.

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

Общение с пользователями

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

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

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

Вместо послесловия

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

Хочется попробовать использовать Vagrant при разработке, это позволит ещё быстрее и проще разворачивать девелоперское окружение. Очень хочется попробовать Selenium для автоматического тестирования проекта (веб-версии и мобильных клиентов). Для более качественного тестирования нового функционала не хватает возможности включать оный по критериям, например, только на сотрудников компании или на определённый процент пользователей, хотим попробовать open-source проект Gargoyle для этого. В ближайшее время, по примеру других Python-проектов в нашей компании, наша команда собирается внедрить Arcanist: надстройку над git для работы с Phabricator из командной строки в репозитории проекта. Это позволит ещё больше упростить процесс code-review и облегчить разработку.

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

Владимир Рудных,
Технический руководитель Календаря Mail.Ru.

Автор: Dreadatour

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js