Может ли команда разработки быть спокойной 8 марта, если вы в сервисе №1 по доставке цветов? Наша история.
Меня зовут Дима, я работаю техническим директором в Flowwow. Мы развиваем маркетплейс локальных магазинов, которые продают красивые букеты и подарки. В нашей R&D команде сейчас 30 разработчиков, и мы используем обширный стек технологий — условно, от Ansible до Kotlin.
У нас есть несколько ключевых дат, в которые количество продаж взлетает на порядок — День матери, 14 февраля и 8 марта. Мы научились проходить эти периоды почти безболезненно и с технической стороны, и со стороны бизнесовой: «уровень негатива» пользователей в пики находится на уровне любого обычного дня, а техническая команда не поднимает упавшую платформу.
Как и у любого процесса, у нашего тоже есть предыстория.
Как проходят праздники для Flowwow?
Сейчас в обычный день у нас около 3 500 заказов. Главные “цветочные” праздники в году – День матери, 14 февраля и 8 марта – означают для нас рост числа покупок в 10, 15 и даже 20 раз. Здесь же учитываем, что и среднее количество заказов в день увеличивается в 2-3 раза ежегодно.
Важный момент – не только быстро масштабироваться, но и быстро снижать обороты после прохождения пика. Так, в 2022 году мы заметили интересную динамику: если предыдущие два года пользователи заказывали подарки и букеты накануне праздника, то в этом году большее количество заказов происходило день в день. Такой эффект, конечно, срабатывает как дополнительная нагрузка.
И хотя пиковые нагрузки в нашем случае легко прогнозируемы, мы не всегда умели готовиться к ним как следует. Вот два тому примера:
14 февраля 2017 года
Мой отпуск: Домбай, горы, я на высоте 3 000 метров ловлю свежий воздух и сигнал, чтобы быть на связи, ведь мы с командой спасаем падающие от нагрузки серверы. А тогда было всего 3K заказов за 2 дня, что в 13 раз меньше, чем на последнее 14 февраля.
День матери 2020 года
Праздник внезапно стал популярнее в стране, и наш сервис стал популярнее — все сошлось. Предыдущие годы трафик на День матери рос не больше чем в 2 раза, а в 2020 году увеличился в 7 раз. Мы оказались не готовы к такому всплеску – ни морально, ни физически. В итоге мы справились, но это стоило выходных и сна всей команде разработки: в пятницу накануне праздника я ушел с работы в два ночи, следующие два дня мы также трудились – поддерживали и чинили платформу в экстренном режиме.
Опыт не прошел даром – мы поняли, что теперь есть еще один бизнесовый пик в году и те работы, которые раньше стартовали в январе (перед 14 февраля и 8 марта), стали запускать уже в октябре. С тех пор ноябрь мы встречаем во всеоружии.
Как подготовиться к пику?
Мы разделяем подготовку к пиковым периодам на три направления:
поиск узких мест и оптимизация текущей инфраструктуры;
помощь команде поддержки;
масштабирование серверов.
Оптимизация приложения
При подготовке к пикам первым делом мы анализируем наше приложение, потому что в другие периоды мы так сконцентрированы на скорости разработки продукта, что до оптимизации не всегда доходят руки. Как правило, выявляются следующие пункты на улучшение:
медленные запросы к базе данных или большое их количество,
сложная логика на уровне приложения,
медленная работа сторонних приложений, с которыми идет обмен данными.
Внутри мы формируем отдельную команду разработчиков, которую освобождаем от бизнес-задач и даем возможность заниматься только оптимизацией кода приложения и запросов баз данных. Обычно на оптимизацию уходит месяц до пикового события. Тут хорошо работает принцип Парето: оптимизация 20% самых узких мест закрывает 80% проблем с производительностью, которые можно решить в коде и в базе данных.
Вообще получается удобно: начинаем оптимизировать в октябре под День матери (последние выходные ноября), потом пик 14 февраля как генеральная репетиция и 8 марта – премьера сезона. Как правило, “оптимизационного заряда” в это время нам хватает, и мы спокойно живем до октября следующего года.
Помощь команде поддержки
Параллельно команда разработчиков, которая сфокусирована на развитии админки, идет к команде поддержки и просит указать на самые слабые места в работе с клиентами и партнерами — какую функциональность добавить в чат, какие кнопки вывести в карточки товаров? Поддержка выражает все свои пожелания.
В этом году наша админка получила такие маленькие, но важные обновления:
Оптимизация информации о каждом заказе (краткие сведения о составе заказа, доставке и ее стоимости);
Автоматический расчет примерного времени, за которое курьер доберется до магазина и затем от магазина до клиента;
Фильтр заказов по городам и странам;
Возможность для продавца пожаловаться на отзыв от клиента – в сам день 8 марта это не так актуально, зато уже на следующий день можно разобрать спорные ситуации и поддержать репутацию магазинов, если случилась ошибка.
Масштабирование серверов
Начну с того, как мы масштабировались раньше (и почему это не лучшее решение): мы просто клонировали сервера из образа диска и уводили на копии часть трафика. Плюсы клонирования – это скорость развертывания, но это работало, пока нам хватало пяти серверов. Кроме того, такой метод не предполагает обновления рабочих станций с точки зрения безопасности и производительности. То есть, клонируя сервер, который был конфигурирован в 2017 году, мы получаем зоопарк серверов, современных с точки зрения 2017 года. Также есть и другие ограничения: например, Amazon выпускает сервера на ARM-процессорах, которые эффективнее и дешевле старых на 30%, а операционку из 2017 года на них запустить уже нельзя.
Как мы делаем сейчас: мы описали всю инфраструктуру через IaC, infrastructure as Code. При необходимости запуска дополнительного сервера мы стартуем не клон, а просто новый сервер по нужной нам конфигурации, заливаем данные – и можно давать трафик. На полный переход и описание инфраструктуры у нас ушло около года, но результат стоит того. Здесь нет ограничений по количеству запусков, а еще мы смогли поменять технологический стек с Intel на ARM, используя подход IaC.
Как мы определяем, сколько серверов потребуется под пиковые нагрузки? Во-первых, у DevOps есть статистика за прошлые пики, от которой можно отталкиваться при планировании (условно: какой был rps и какой серверной группировкой мы все это вывезли). Во-вторых, мы спрашиваем у маркетинга, сколько планируется трафика, затем добавляем к этим цифрам 50% в качестве страховки и решаем, сколько серверов и какой мощности нужно запустить.
Что изменилось весной 2022
Этот год можно рассматривать как отдельный кейс. Во-первых, резко изменилось поведение клиентов (я это упоминал в начале статьи): вместо того, чтобы заказать цветы заранее с указанием даты доставки 8 марта, большинство пользователей сделали заказ день в день. Уровень нагрузки, на который мы рассчитывали, был превышен – пригодился тот самый резерв +50% к плану.
Во-вторых, с конца февраля появились дополнительные вызовы:
DDoS-атаки;
возможный уход вендоров – поставщиков услуг и сервисов для онлайн продуктов;
блокировки сервисов и риск оказаться в суверенном рунете.
К кибератакам мы были готовы: нас пытаются сломать при каждом пике, поэтому мы заботимся о надежной защите. В последние два года мы систематически проводим аудит безопасности и исправляем найденные уязвимости в серверах и в нашем коде, чтобы не думать об этом в момент подготовки к высоким нагрузкам.
Были вполне логичные опасения, что Github или Amazon приостановят работу с Россией, поэтому мы в срочном порядке сделали бэкапы всех данных и пользовательского контета на отчественных облаках. Если бы наш основной дата-центр стал недоступен, мы бы смогли запуститься на Яндекс.Облаке за пару дней.
Наконец, мы осознали, что даже если иностранные компании не разорвут отношения с российскими клиентами, иметь критичные узлы IT-инфраструктуры за пределами РФ слишком ненадежно. Поэтому после срочного бэкапа данных мы начали планомерно дублировать критичные узлы в российском дата-центре. Сейчас мы имеем полностью рабочие контуры и в РФ, и за пределами РФ, а между ними налажен информационный обмен, чтобы все работало как единое целое.
Можно представить такой таймлайн готовности:
за две недели до дня Х — включаем на низкую мощность все дополнительные сервера, чтобы понаблюдать за ними подольше; составляем график дежурств: есть DevOps, один инженер команды нагрузки, один инженер для поддержки.
за три-четыре дня до дня Х — объявляем фича-фриз на изменения в продакшене (по мобильным приложениям фича-фриз наступает минимум за неделю). Все решения зарелизили, даем им время настояться: как они будут себя вести, какие ошибки будут выдавать? Здесь же запускаем на полную мощность дополнительные сервера.
за день до дня Х — финально проверяем готовность всех систем и команды.
В день Х работает выбранная смена, система мониторингов собирает информацию о нагрузке, трафике, ошибках. Если что-то пошло не так — есть регламент, по которому DevOps и инженеры нагрузки реагируют на ошибки и принимают решения. Ботам мы поручаем следить за аномалиями, все и всё при деле.
Почему масштабирование заранее — это хорошо
Прошел пиковый период, и мы не только выдохнули, но и подумали на будущее. DevOps фиксирует базовые параметры, которые позволяют его пройти — трафик, число заказов, количество серверов и репликаций. Это позволяет нам строить прогнозы и оценивать мощности для нового периода.
Сейчас мы испытываем почти столько же радости, сколько и получатели цветов и подарков. Вот данные по итогам крайнего пика – 8 марта 2022:
процент опозданий курьеров не выходил за рамки 7,5% (а опозданием мы считаем даже задержку на 5-10 мин),
уровень негатива (оценка 3 и ниже по пятибалльной шкале) составил всего 3,5 %;
количество споров, где понадобилось участие нашей поддержки, оказалось меньше на 200 обращений, чем в прошлом году (тогда как количество заказов возросло на 26 тысяч).
Плюс ко всему, мы можем не работать всей командой в пиковые выходные, а заранее договориться о сменах. Это правда важно.
Буду рад, если поделитесь в комментариях, как вы решаете вопрос масштабирования. А еще было бы очень интересно почитать про кейсы из практики, когда нагрузка оказывалась в разы больше запланированной: обычно такие ситуации – кладезь нестандартных решений.
koreychenko
Ожидал прочитать про Kubernetes, autoscaling, какие параметры приложения являются ключевыми для определения, что нужна еще одна реплика.
Я правильно понял из написанного, что вы руками задаете количество серверов в соответствии с тем, что вам рассказал отдел маркетинга? Я вижу тут кучу места для оптимизации костов, ибо, ожидания и реальность не всегда совпадают. Ну и не понятно зачем нужны включенные сервера, если нагрузки еще/уже нет.
Также не совсем понятно, что значит "Здесь же запускаем на полную мощность дополнительные сервера." Сервер он либо работает, либо не работает. Это значит, что вы начинаете на него давать больше трафика? Сколько давать трафика и как распределять его между репликами тоже вручную решается?
makar_crypt
ожидал прочитать про Azure Service Fabric.