Как за ограниченное время из готовых компонентов создать и запустить по-настоящему нагруженный проект? Рассмотрим пример метрик, архитектуры, технических ограничений и подходов к проектированию систем на примере проекта «Экологический диктант».
Помогут нам в этом, два главных человека из компании Старботс.рф - Станислав Жуковский, руководитель проекта, и Василий Шалимов, архитектор и разработчик фич в части бэкенда. Они расскажут, как собрали сервис онлайн-тестирования за 2 месяца, вместо 8 плановых, а также про человеческий фактор, с которым они столкнулись во время работы.
Что такое Экодиктант?
Многие сейчас говорят про бережное отношение к экологии, электронный движ и прочее. Международный проект Экодиктант нацелен на то, чтобы проверить знания об экологии и природопользовании не только у школьников и студентов, но также у взрослого населения. Вот немного цифр Экодиктанта 2021:
Срок запуска 2 месяца
3 миллиона авторизованных пользователей из 35 стран
1 миллион пройденных тестов за 5 дней
1000 корпоративных клиентов, среди которых Газпром, Норникель, Росатом с подразделениями и МЧС и сотрудники других компаний.
Но это только то, что касается онлайн пользователей. Был ещё большой блок, связанный с офлайн проведением мероприятия: распечатки анкет, организация волонтеров для помощи в подсчете результатов и прочие орг.моменты. ТЗ проекта составлялось более полугода и содержало более 120 страниц. Схема включала более 100 микросервисов со слабой связанностью, s3 хранилища, шардирование базы на основе регионального принципа, и ещё много чего.
В итоге на выполнение проекта было оставлено всего 2 месяца. Команда Старботс.РФ высказала опасения заказчику, что за такое время не успеют сделать проект на основе микросервисов и обеспечить стабильную работу при таком масштабе пользователей. К тому же нужно было ещё сделать публичную часть сайта со страницей в Википедии, хотя на тот момент не был утверждён даже дизайн.
По итогу разработчики предложили исполнительной дирекции «Экодиктанта» идти по пути MVP (минимально жизнеспособного продукта), который можно сделать на чём угодно. Станислав и Василий выбрали Django, потому что это был самый оптимальный выбор в сложившихся условиях, в том числе и для highload проект, к сожалению, Laravel использовать было нельзя, потому что у заказчика с ним были проблемы ранее. При этом главная фича проекта — прохождение самого диктанта, была реализована на React. Всё остальное: регистрация, аутентификация и Wiki — осталось на Django, чтобы снизить нагрузку.
Рассмотрим, как они разрабатывали этот проект по неделям.
До диктанта 11 недель
Всего было 12 недель, но одна из них ушла на согласование и прочее, поэтому на старте осталось лишь 11.
![https://lh3.googleusercontent.com/F12ZfLcuUFym8_hwek9l_ZoEHjzEkS8jZOQshGeKxYSuwyzqWB-BzuskU7DaPZCPrgMXVhDxwCJw3jVUGN0_2RJeMB-dw6ZAl2YoRxwjrMYfCk435UrRMHcxpn8JLySBzrzrD8jeqx9MTBtUTRkuaw](https://habrastorage.org/getpro/habr/upload_files/d68/4b0/e78/d684b0e78c1666483595432ae27adf43.jpg)
Нужно было провести нагрузочное тестирование, чтобы показать заказчику, что Django и React подходят по метрикам. Чтобы приступить к тестированию требовалось собрать более или менее согласованный дизайн, статику и прототип React приложения.
Для оптимизации микросервисов проекту разработчикам требовалось много «железа». Этот вопрос был решен с помощью технического оснащения от Мегафон.
10 недель
![https://lh3.googleusercontent.com/rjLWxi0ZGAYbGZH4_AhW8GurUjb8CzSx7hlZ-UlAFHX_d2iDpa6Vbx5iSKMQAhlbpstqCapUc4uqKXVgI4sL1Y0ZqxUSzPeYRbsE4vrPYlibfXPBxyqW_pCxhVhREhjyBSBumvm0HGzxnviBi6_dNw](https://habrastorage.org/getpro/habr/upload_files/a87/a01/65f/a87a0165f3e2d4b239e87602e973ef89.jpg)
Было два щекотливых момента, которые настораживали заказчика:
Выбор сервера web-приложения Django: uWSGI.
Оказалось, что заказчик был очень начитанный, проштудировал все статьи Хабра за неделю. Он просил Bjoern на этот проект из-за его асинхронности и наличия большого количества RPC. Но Василий со Станиславом смогли убедить заказчика оставить uWSGI, потому что по количеству ошибок он стоит до последнего, пока не закончится память.
![https://lh4.googleusercontent.com/psCUcdazOMmR8tJQGYhJkwp7G0hweS0AWN7RCjtDHELKm4-P_rjyrCJy0XrqUgnlT5OHMDwcotOZwTWlWe1Q6V7CUSrDI7C9MbvG1E3W9q7jLWMt7hCCYi20Lenp53FpcBrPGuQGxf5NiFRd12pfNg](https://habrastorage.org/getpro/habr/upload_files/823/47d/09d/82347d09df530705fe9b1921c89f8364.jpg)
Выбор балансировщика: HAProxy.
Заказчик спрашивал, чем не подошли Nginx, Envoy и требовал тесты. Тесты были успешно выполнены, что позволило оставить HAProxy.
8 недель
![https://lh6.googleusercontent.com/mwVDPZUJrNa4tjAbjQttlx9LRgEWhzS5LijZV-adzrLzpNtLVljjMWApnBq2TibsBisNsbp8GKLdXNn9qrxElXETxUYxKNbGkJC88yC0UF0NPwQwoB1iwZdSOGHlUYrQ9TeE8FVMwBf3Das6jKqytA](https://habrastorage.org/getpro/habr/upload_files/1e4/7b5/492/1e47b549207603a33234deb0a5282821.jpg)
Настал день нагрузочного тестирования. Поскольку проект жил в облаке Мегафона, логично было вынести его за пределы их инфраструктуры, чтобы получить валидные результаты. Поэтому техническая команда проекта приняла решение поднять под образы Мегафона машины с Яндекс.Танком в Яндекс.Облаке. Поскольку у них уже была собрана статика, то получился не гипотетический конь в вакууме, а конкретное React-приложение с медийными материалами, которые планировалось показать через 8 недель. Кроме этого уже имелись размеры главной страницы всех типов файлов.
RPC заказчика устроило при нормах потребления по контейнерам. Поэтому инфраструктура была утверждена и можно было начинать полноценную разработку.
7 недель
![https://lh6.googleusercontent.com/d_qKqi0RV-fcE7pcLMZ_cv442d5doNut4TrsgqF3UJBHgkpK-ZhRHP9keRlt6wx3V6_-vjlS5DZ9dOaZaF6fnjwIuoTFIHKp2CAJ-FJZf4oT8cgTxw7tRHYk5CUOHP2ZUsfBbJBPHjiAs19BINLeFA](https://habrastorage.org/getpro/habr/upload_files/9d2/db4/da7/9d2db4da788e5f6e958e303cdc54d572.jpg)
Django отвечал за публичную часть: аутентификацию, React — за само прохождение диктанта, он гонял пользовательские сессии через JWT.
Не все из 5 ведущих библиотек одинаково быстро выпускают токены, поэтому их всегда нужно тестировать на своём проекте. А после нагрузочного тестирования просто поменять фичи или либы, и выбрать ту связку, в которой токены выпускаются вовремя.
6 недель
![https://lh4.googleusercontent.com/xZC1TRSQKjRMojbcqTpR4Wkj8h3Su-FwCVuT1C3I3lpufl9NIOzU9lfyH5AcCl0KGfo_ZDQiHP7jB195_8xyx3iIt9FgKk5ea9klbaWbz0ZIknIZnkc3xd5Hubpc4jPNgu2wJ2hyQxvCtMC0bW7swA](https://habrastorage.org/getpro/habr/upload_files/e27/120/685/e2712068548774db2ba3ef1140acde6e.jpg)
На 6 неделе заказчик вспомнил, что в старом проекте на Laravel осталось 300 тысяч учётных записей, которые надо бы перенести. При этом оповестить пользователей о том, что нужно сменить пароль, они не успевали. Поэтому пришлось давить нагрузкой: поднимать микросервисы под Laravel. Но возникла проблема: в Laravel использован bcrypt 128 bit, а в Django — 256 bit. Пришлось под 300 тысяч учёток в бэке отдельно писать ветку, чтобы пользователи, не меняя пароль, могли получить токены Django и пройти дальше.
5 недель
![https://lh5.googleusercontent.com/G1Zour3ZrhtIWNZk6w861aO1O4-Skwbo7xxznQmbEdu4ARlYBirT93eE-IArFuxlYJsb-p4KQwxYKqZ0mNkrlTop3nZgIoNnVuO1GeDGEV3OBA3s-9EMlDDf80oKW3XpmfIX_2GpztI8BgUvlxMEbA](https://habrastorage.org/getpro/habr/upload_files/b80/5b9/8ad/b805b98ad29c16d3822dc953d42125f8.jpg)
Стоит отметить, что глобально 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 недели
![https://lh3.googleusercontent.com/BX0iY9eI-rc-eE6sRig5rm4wRV-atNZ6fb6ch2z_7VyMbjDPqvK-5LPhY5wsqsEGs6tl47PxkAlUjnbQgqN9Vr9lNsUFnsKwhjbjV10NXSW_9PTrLJwGunzuwAGH6gn9__rCi5lEbbRlVP9iueNSgw](https://habrastorage.org/getpro/habr/upload_files/9fa/1be/b50/9fa1beb509305f368936dec00fa14b70.jpg)
На начало второго месяца была готова публичная часть (медиатека, регистрации), почта, оповещения в госслужбы, реферальные ссылки компаниям-участникам, чтобы все работники РЖД, Газпрома, Норникеля, которые связаны с экологией, их увидели. Во многих организациях, где работает большое количество сотрудников - это целое мероприятие.
Если у вас совсем времени в обрез, некоторые вещи, связанные с мощностями, можно отдать техническому спонсору. В случае Экодиктанта это был Мегафон. Они настроили аппаратную защиту от DDoS, поэтому команде Станислава с Василием ничего на своей стороне делать не пришлось в этом вопросе.
3 недели
![https://lh3.googleusercontent.com/nucdSZLxulA34XLZQTpEwCYCsbmiqzPDtERmT-Xu_QFC_OqDOOgfx3k3faZISBt0Eusw5ZiuXNC6b8FkD-dEPjQ6aZk-NJuO3djTV9mDujMgWsgwO70BEiW3a1E8w75kC1ElO2QoH5CGRjdaDqVOAA](https://habrastorage.org/getpro/habr/upload_files/924/afb/a9f/924afba9f89e3a794076d5ed009b75e2.jpg)
Вовсю шла выкладка контента по 4 категориям: до 18, 18+, экологи, не экологи. Под каждую из категорий заказчик предоставил контент: видео, картинки, текстовые PDF-файлы, звуковые записи и прочее.
Для ускоренной прогрузки медиа файлов, по просьбе заказчика были выключены фильтры конвертации и оптимизации загружаемых файлов. Что привело к ошибочной загрузке на главную страницу больших файлов в не сжатом виде, что в свою очередь привело к превышению квоты пропускной способности канала.
2 недели
![https://lh5.googleusercontent.com/kLzgNqBepyEhO0ujXqhZA9g3Y9INpSA09RyYFdecfeWxV4ZnH_ScDs9SdowaVI7KCyPaTSEIALJ7MXzFDzLSSVaTgcFHCg9aAHa9-vRUXXalrXjz9SJmLsHAe5X0JSMAzVatIt2sRMu1nf3BKaEmkg](https://habrastorage.org/getpro/habr/upload_files/569/5aa/334/5695aa334807625bcb97f3233317a6be.jpg)
Поскольку всё находилось в Kubernetes, по автомасштабированию был вопрос. Мегафон сказал, что даст железа столько, сколько нужно, но только тогда, когда будет нагрузка. Он попросил сначала всё оптимизировать, а потом уже забирать аллоцированные ядра.
Поскольку ограничений со стороны железа не было, то команде не подошли методики горизонтального, вертикального и автомасштабирования в Kubernetes. Ключевой метрикой для было не потребление, а скорость ответа, чтобы контейнер всегда оставался жив.
![https://lh5.googleusercontent.com/lwQucmqNTLS0cjIOL4H2_8Htnk3b95SQoZVpqwraRimCucTmwGyjjqMmlNbja9yVwSOQHb71TOTrX66GaDv-e_j_6OU6JxOzXdDKtQgQd73F0KqZrC7BHoPFb8aKeSaJxPIOPPdunetfEGJD4IJGpg](https://habrastorage.org/getpro/habr/upload_files/312/e12/9ca/312e129caf178a47ff487aa410c4a427.jpg)
Таким образом, основной метрикой было то, с какой скоростью Django машина отдаёт публичную часть, с какой скоростью React-приложение пропускает через себя вопросы-ответы и с какой скоростью отвечает Rest. Под эту историю в соответствии с документацией Kubernetes девопсы подняли сервер метрик и Prometheus. А дальше, чтобы убрать выбросы, на основе опроса поднятых подов в Django и времени ответа через сглаживание, происходило расширение нужного количества подов Django машин.
![https://lh5.googleusercontent.com/BzOPVupDm_VwiM3LdyJXlXAvXLADHsgIq2OGcS_-G96d20DqkLbwYUtGHJeqECmjWteUtk10Bw7F9DwVWIvkjOknWMepQT8FD94Zt4t88GRAm_ngDbOWCWlJwz1OeeVc8OAldQdcpvuuVOA9oQn9BA](https://habrastorage.org/getpro/habr/upload_files/0de/de9/dcc/0dede9dcc68f5692e4d55fc7485978a6.jpg)
React в этом проекте вёл себя очень скромно. В то время как Django прямо ел и ел ресурсы пропорционально росту количества регистраций и прохождений тестов.
1 неделя
![https://lh3.googleusercontent.com/aV4Xh0FAJmlI_VpB89Q7LEYbXffEFspfu-Q5HiyZu8hwi9D86W5WNmj-Iua2YIQAdHdiIVCgvXZoNT1l1RYTiK5Eg2VYn7skWSzhJ-HY06104l_PB4ZipQy97yeza1vzggqPMF_30o5Yo8sM63kUNA](https://habrastorage.org/getpro/habr/upload_files/fcb/970/0c9/fcb9700c9cd38a4953416cf0dac5befb.jpg)
В 0 часов разработчики узнали, что у проекта деградация на 5 секунд в публичной части. Они не успевали разворачиваться под контейнера. Пришлось разбираться, в чём дело, оказалось, что это Госуслуги начали рассылку.
Дело в том, что Владивосток проснулся в 8 утра, а это 0 часов по Московскому времени. Тогда сразу пошла нагрузка по Кубер-кластеру. Но Кубер не в момент рождает поды, есть задержка. Её хватило, чтобы получить деградацию. Конечно, команда быстро перестроила настройки, предразвернули поды и погасили деградацию. Однако, если бы была информация о рассылке по Госуслугам заранее, то к этому вопросу отнеслись бы пристальней.
Диктант
![https://lh3.googleusercontent.com/5AdRX2rgbBDEeqTHu7KcNDxxhgLGgDbUdyU865qvuVo_QnYClIXJFWwXQ4zq59D4QVn02jcAhuOo9lw4A3BX2o86AY26nVdbTuuuOVRTPXHGXZV1Hwp8Id9jDHWPr8a0ViWRmhB2uiPHiOEIwOqXYA](https://habrastorage.org/getpro/habr/upload_files/9c4/7f9/902/9c47f990254ebd339c92eece106761eb.jpg)
Возможно, вам знакома ситуация, когда люди не могут подключиться к Госуслугам, электронному дневнику и другим сервисам, связанным с обучением. Опасения были и у команды Старботс.рф. Но опасения были напрасны.
Василий отодвинул всё, что не касалось главной фичи, а Станислав ограждал его и остальную команду от яростных атак заказчика по поводу цвета иконок и прочего. Главное, что диктант выдержал и прошёл. В офлайн и в онлайн режимах не было нареканий. Мы это знаем, потому что в конце диктанта было окошко: «Оставьте свой отзыв о том, как всё прошло». Среди более 2 тысяч отзывов были отрицательные, но они не связаны с технической стороной проекта. Это прямо погрело сердце разработчикам, хотя во время подготовки их стороны были и фейлы.
Ошибки и проблемы
2 падения;
Уже во время прохождения диктанта заказчик сообщил, что: «Мария Ивановна и Светлана написали в социальных сетях, что не могут зайти!». Станислав с Василием начали разбираться и включили поиск LIKE в Django.
В это время Postgres сожрал всю память и CPU! Но так как технические возможности были, то просто умножили на 2 и подняли. Но потом он опять упал. В такой критической ситуации, Станислав с Василием подняли директиву и откатили назад на предыдущую версию. Это и спасло. Мария Ивановна, конечно, расстроилась, что не смогла зайти, но зато все остальные смогли.
Лёг кластер Кубер;
Если есть отказоустойчивый сервер, разделяйте его на разные дата-центры. Команда этого сначала не сделала и, когда у Мегафона возникли проблемы на VMWARE, у них упал Кубер на час.
2 DDoS-атаки: успешно отбиты аппаратно.
Выводы
→ Говорите «нет» срокам!
Чудес не бывает. Если нужно всё оптимизировать, то времени нужно много. Если делать всё быстро, то требуется много ресурсов, поэтому смело просите больше «железа» и используйте подходы, инструменты MVP.
→ Прогнозируйте всплеск трафика.
Какие бы у вас не были крутые девопсы и подсчёты, перестрахуйтесь и запланируйте все всплески: разверните поды в Кубере заранее и умножьте их количество на два.
→ Кластеры Кубер тоже смертны!
Шардируя Кубер на разные дата-центры, учитывайте, что они могут ломаться.
AntonOcean
А вывод не использовать Django? :peka:
dph
Вот да. Вроде бы вполне скромные НФТ, интересна только рассылка писем, все остальное совсем небольшое.