Как за ограниченное время из готовых компонентов создать и запустить по-настоящему нагруженный проект? Рассмотрим пример метрик, архитектуры, технических ограничений и подходов к проектированию систем на примере проекта «Экологический диктант».
Помогут нам в этом, два главных человека из компании Старботс.рф - Станислав Жуковский, руководитель проекта, и Василий Шалимов, архитектор и разработчик фич в части бэкенда. Они расскажут, как собрали сервис онлайн-тестирования за 2 месяца, вместо 8 плановых, а также про человеческий фактор, с которым они столкнулись во время работы.
Что такое Экодиктант?
Многие сейчас говорят про бережное отношение к экологии, электронный движ и прочее. Международный проект Экодиктант нацелен на то, чтобы проверить знания об экологии и природопользовании не только у школьников и студентов, но также у взрослого населения. Вот немного цифр Экодиктанта 2021:
Срок запуска 2 месяца
3 миллиона авторизованных пользователей из 35 стран
1 миллион пройденных тестов за 5 дней
1000 корпоративных клиентов, среди которых Газпром, Норникель, Росатом с подразделениями и МЧС и сотрудники других компаний.
Но это только то, что касается онлайн пользователей. Был ещё большой блок, связанный с офлайн проведением мероприятия: распечатки анкет, организация волонтеров для помощи в подсчете результатов и прочие орг.моменты. ТЗ проекта составлялось более полугода и содержало более 120 страниц. Схема включала более 100 микросервисов со слабой связанностью, s3 хранилища, шардирование базы на основе регионального принципа, и ещё много чего.
В итоге на выполнение проекта было оставлено всего 2 месяца. Команда Старботс.РФ высказала опасения заказчику, что за такое время не успеют сделать проект на основе микросервисов и обеспечить стабильную работу при таком масштабе пользователей. К тому же нужно было ещё сделать публичную часть сайта со страницей в Википедии, хотя на тот момент не был утверждён даже дизайн.
По итогу разработчики предложили исполнительной дирекции «Экодиктанта» идти по пути MVP (минимально жизнеспособного продукта), который можно сделать на чём угодно. Станислав и Василий выбрали Django, потому что это был самый оптимальный выбор в сложившихся условиях, в том числе и для highload проект, к сожалению, Laravel использовать было нельзя, потому что у заказчика с ним были проблемы ранее. При этом главная фича проекта — прохождение самого диктанта, была реализована на React. Всё остальное: регистрация, аутентификация и Wiki — осталось на Django, чтобы снизить нагрузку.
Рассмотрим, как они разрабатывали этот проект по неделям.
До диктанта 11 недель
Всего было 12 недель, но одна из них ушла на согласование и прочее, поэтому на старте осталось лишь 11.
Нужно было провести нагрузочное тестирование, чтобы показать заказчику, что Django и React подходят по метрикам. Чтобы приступить к тестированию требовалось собрать более или менее согласованный дизайн, статику и прототип React приложения.
Для оптимизации микросервисов проекту разработчикам требовалось много «железа». Этот вопрос был решен с помощью технического оснащения от Мегафон.
10 недель
Было два щекотливых момента, которые настораживали заказчика:
Выбор сервера web-приложения Django: uWSGI.
Оказалось, что заказчик был очень начитанный, проштудировал все статьи Хабра за неделю. Он просил Bjoern на этот проект из-за его асинхронности и наличия большого количества RPC. Но Василий со Станиславом смогли убедить заказчика оставить uWSGI, потому что по количеству ошибок он стоит до последнего, пока не закончится память.
Выбор балансировщика: HAProxy.
Заказчик спрашивал, чем не подошли Nginx, Envoy и требовал тесты. Тесты были успешно выполнены, что позволило оставить HAProxy.
8 недель
Настал день нагрузочного тестирования. Поскольку проект жил в облаке Мегафона, логично было вынести его за пределы их инфраструктуры, чтобы получить валидные результаты. Поэтому техническая команда проекта приняла решение поднять под образы Мегафона машины с Яндекс.Танком в Яндекс.Облаке. Поскольку у них уже была собрана статика, то получился не гипотетический конь в вакууме, а конкретное React-приложение с медийными материалами, которые планировалось показать через 8 недель. Кроме этого уже имелись размеры главной страницы всех типов файлов.
RPC заказчика устроило при нормах потребления по контейнерам. Поэтому инфраструктура была утверждена и можно было начинать полноценную разработку.
7 недель
Django отвечал за публичную часть: аутентификацию, React — за само прохождение диктанта, он гонял пользовательские сессии через JWT.
Не все из 5 ведущих библиотек одинаково быстро выпускают токены, поэтому их всегда нужно тестировать на своём проекте. А после нагрузочного тестирования просто поменять фичи или либы, и выбрать ту связку, в которой токены выпускаются вовремя.
6 недель
На 6 неделе заказчик вспомнил, что в старом проекте на Laravel осталось 300 тысяч учётных записей, которые надо бы перенести. При этом оповестить пользователей о том, что нужно сменить пароль, они не успевали. Поэтому пришлось давить нагрузкой: поднимать микросервисы под Laravel. Но возникла проблема: в Laravel использован bcrypt 128 bit, а в Django — 256 bit. Пришлось под 300 тысяч учёток в бэке отдельно писать ветку, чтобы пользователи, не меняя пароль, могли получить токены Django и пройти дальше.
5 недель
Стоит отметить, что глобально web проект на проде уже существовал с первой недели. Потому что его большая часть — это медиатека с довольно большим количеством контента, который нужен участникам для того, чтобы с ним ознакомиться, подучится для онлайн-тестирования. Поэтому к моменту, когда нужно было прикручивать авторизацию и уведомлять пользователей о регистрации, портал, как источник медиафайлов, уже существовал.
Во второй части оставалась ещё задача про рассылку почтовых уведомлений. С учётом опыта прошлого года и уверенного предположения заказчика о том, что Госуслуги сделают рассылку по всей стране, было выставлено требование: сервис должен отправлять минимум 50, а лучше 60-70 писем в секунду.
Обычно, когда мы говорим про сервис почтовых рассылок, вспоминаются MailChimp или UniSender. Но когда разработчики посмотрели на требуемые цифры, то поняли, что эти параметры есть только у Amazon. Однако, Amazon ничего просто так давать не собирался. Он в свою очередь потребовал 15 тысяч долларов и 10% от квот в течении 3-х месяцев.
3-х месяцев в запасе не было, чтобы кому-то что-то доказывать, поэтому в век, когда все пользуются СМС-верификациями или звонками, пришлось самим собирать почтовик —- сделали на Postfix, потом размножили. В общей сложности удалось довести показатели рассылки до 70 писем в секунду. У команды разработчиков было 2 домена, которые в прошлом году участвовали в демонстрации web-портала, поэтому их можно было считать условно прогретыми. В итоге Василий со Станиславом выпустили всё, что было нужно, вплоть до правильных DKIM подписей и по-человечески настроенных портов.
Если вы когда-нибудь будете настраивать свой почтовик с такими объёмами отправки, лучше сразу приобретите на это дело доменов 5. В случае с Экодиктантом, 1 домен «упал» и попал в black-list примерно на 2-3 суток. Поэтому было принято решение переключиться на второй резервный, но попутно делать всё возможное, чтобы скорее вывести из black-list’а упавший домен. Когда его разбанили, то перевели все на основной домен. В общей сложности такое мероприятие отняло около недели. За это время только менее 1% участников людей не удалось получить письмо с подтверждением регистрации с первого раза.
Самое интересное, что потребность в рассылке была необходима, поскольку по итогам прохождения тестирования участники получали диплом, который можно было распечатать в нормальном формате и повесить себе на стенку. Он отправлялся на электронную почту, поэтому организатор по опыту прошлого года уже понимал, что была куча участников, которые регистрировались на непонятную почту, проходили тестирование, а после спрашивали, где их диплом. Учитывая опыт прошлых лет пользователей попросили регистрироваться только валидные почты.
4 недели
На начало второго месяца была готова публичная часть (медиатека, регистрации), почта, оповещения в госслужбы, реферальные ссылки компаниям-участникам, чтобы все работники РЖД, Газпрома, Норникеля, которые связаны с экологией, их увидели. Во многих организациях, где работает большое количество сотрудников - это целое мероприятие.
Если у вас совсем времени в обрез, некоторые вещи, связанные с мощностями, можно отдать техническому спонсору. В случае Экодиктанта это был Мегафон. Они настроили аппаратную защиту от DDoS, поэтому команде Станислава с Василием ничего на своей стороне делать не пришлось в этом вопросе.
3 недели
Вовсю шла выкладка контента по 4 категориям: до 18, 18+, экологи, не экологи. Под каждую из категорий заказчик предоставил контент: видео, картинки, текстовые PDF-файлы, звуковые записи и прочее.
Для ускоренной прогрузки медиа файлов, по просьбе заказчика были выключены фильтры конвертации и оптимизации загружаемых файлов. Что привело к ошибочной загрузке на главную страницу больших файлов в не сжатом виде, что в свою очередь привело к превышению квоты пропускной способности канала.
2 недели
Поскольку всё находилось в Kubernetes, по автомасштабированию был вопрос. Мегафон сказал, что даст железа столько, сколько нужно, но только тогда, когда будет нагрузка. Он попросил сначала всё оптимизировать, а потом уже забирать аллоцированные ядра.
Поскольку ограничений со стороны железа не было, то команде не подошли методики горизонтального, вертикального и автомасштабирования в Kubernetes. Ключевой метрикой для было не потребление, а скорость ответа, чтобы контейнер всегда оставался жив.
Таким образом, основной метрикой было то, с какой скоростью Django машина отдаёт публичную часть, с какой скоростью React-приложение пропускает через себя вопросы-ответы и с какой скоростью отвечает Rest. Под эту историю в соответствии с документацией Kubernetes девопсы подняли сервер метрик и Prometheus. А дальше, чтобы убрать выбросы, на основе опроса поднятых подов в Django и времени ответа через сглаживание, происходило расширение нужного количества подов Django машин.
React в этом проекте вёл себя очень скромно. В то время как Django прямо ел и ел ресурсы пропорционально росту количества регистраций и прохождений тестов.
1 неделя
В 0 часов разработчики узнали, что у проекта деградация на 5 секунд в публичной части. Они не успевали разворачиваться под контейнера. Пришлось разбираться, в чём дело, оказалось, что это Госуслуги начали рассылку.
Дело в том, что Владивосток проснулся в 8 утра, а это 0 часов по Московскому времени. Тогда сразу пошла нагрузка по Кубер-кластеру. Но Кубер не в момент рождает поды, есть задержка. Её хватило, чтобы получить деградацию. Конечно, команда быстро перестроила настройки, предразвернули поды и погасили деградацию. Однако, если бы была информация о рассылке по Госуслугам заранее, то к этому вопросу отнеслись бы пристальней.
Диктант
Возможно, вам знакома ситуация, когда люди не могут подключиться к Госуслугам, электронному дневнику и другим сервисам, связанным с обучением. Опасения были и у команды Старботс.рф. Но опасения были напрасны.
Василий отодвинул всё, что не касалось главной фичи, а Станислав ограждал его и остальную команду от яростных атак заказчика по поводу цвета иконок и прочего. Главное, что диктант выдержал и прошёл. В офлайн и в онлайн режимах не было нареканий. Мы это знаем, потому что в конце диктанта было окошко: «Оставьте свой отзыв о том, как всё прошло». Среди более 2 тысяч отзывов были отрицательные, но они не связаны с технической стороной проекта. Это прямо погрело сердце разработчикам, хотя во время подготовки их стороны были и фейлы.
Ошибки и проблемы
2 падения;
Уже во время прохождения диктанта заказчик сообщил, что: «Мария Ивановна и Светлана написали в социальных сетях, что не могут зайти!». Станислав с Василием начали разбираться и включили поиск LIKE в Django.
В это время Postgres сожрал всю память и CPU! Но так как технические возможности были, то просто умножили на 2 и подняли. Но потом он опять упал. В такой критической ситуации, Станислав с Василием подняли директиву и откатили назад на предыдущую версию. Это и спасло. Мария Ивановна, конечно, расстроилась, что не смогла зайти, но зато все остальные смогли.
Лёг кластер Кубер;
Если есть отказоустойчивый сервер, разделяйте его на разные дата-центры. Команда этого сначала не сделала и, когда у Мегафона возникли проблемы на VMWARE, у них упал Кубер на час.
2 DDoS-атаки: успешно отбиты аппаратно.
Выводы
→ Говорите «нет» срокам!
Чудес не бывает. Если нужно всё оптимизировать, то времени нужно много. Если делать всё быстро, то требуется много ресурсов, поэтому смело просите больше «железа» и используйте подходы, инструменты MVP.
→ Прогнозируйте всплеск трафика.
Какие бы у вас не были крутые девопсы и подсчёты, перестрахуйтесь и запланируйте все всплески: разверните поды в Кубере заранее и умножьте их количество на два.
→ Кластеры Кубер тоже смертны!
Шардируя Кубер на разные дата-центры, учитывайте, что они могут ломаться.
AntonOcean
А вывод не использовать Django? :peka:
dph
Вот да. Вроде бы вполне скромные НФТ, интересна только рассылка писем, все остальное совсем небольшое.