Как настроить веб-приложение под высокие нагрузки

Привет, меня зовут Александр Ададуров. Я — руководитель проектов ФГБУ «Центр информационно-технического обеспечения». В этой статье я опишу опыт настройки сайта с образовательным контентом под нагрузку в пиках до 15 000 запросов в секунду или до нескольких миллионов пользователей в день. 

Образовательный контент сайта представлял собой иллюстрированные HTML-страницы, видеоуроки и различные интерактивные задания, преимущественно на JavaScript, которые проверяли правильность выполнения заданий запросами к бэкенду. Сайт жил спокойной жизнью и вяло развивался до введения локдаунов в связи с распространением COVID-19. Первые месяцы карантина существенно изменили код приложения, его архитектуру и даже серверную инфраструктуру, на которой оно располагалось. 

37ba61a92900115fed253b4094d54a4a.png

Первоначальная архитектура

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

Cайт был написан на PHP-фреймворке Symfony 3, без четкого разделения на фронт и бэк. Веб-интерфейсы рендерили с помощью шаблонизатора Twig, для интерактива использовали преимущественно JQuery. В качестве СУБД была PostgreSQL 9.6, а часть данных по инициативе разработчиков кешировалась в NoSQL СУБД Redis. На сайте был API для загрузки и многоэтапной обработки нового контента, для этого была выстроена система очередей на двух брокерах RabbitMQ.

Проект располагался на 16 физических серверах, фронтенды и бэкенды — по 24 ядра и 128 ОЗУ каждый, ноды СУБД имели 56 ядер и 512 ГБ ОЗУ. В каждом сервере было по четыре 10-гигабитных сетевых интерфейса, которые давали агрегированный канал шириной 40 Гбит. На нодах стояли жесткие диски по 2 ТБ с установленной ОС, а на бэкенд-нодах дополнительно располагался код PHP/Symfony. Разделяемые ресурсы, такие как изображения, видео и загружаемые файлы, которые требовались на всех нодах, хранились в СХД и монтировались к каждой ноде в виде сетевых шар NFS.

Первоначальная архитектура приложения

Первоначальная архитектура приложения

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

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

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