Спасти за 60 дней: новая архитектура для ресурса с большой нагрузкой
К нам обратился заказчик, который хотел улучшить архитектуру высоконагруженного ресурса на основе Moodle. Сайт имел привычку падать при высокой нагрузке. Ничего необычного, подумали мы. Берем.
Нетривиальность задачи оказалось в том, что кейсов инсталляции сервисов Moodle на ресурсы с нагрузкой >10 тыс. человек нет ни у Яши, ни у других сервисов, к которым мы привыкли. Из коробки ничего не работало, документации тоже не нашлось. Предыдущий исполнитель с задачей не справился и оставил сервис в печальном состоянии.
Срок выполнения задачи – 2 месяца, что добавило остроты проекту перед Новым годом…
Исходные данные
Ресурс (сайт) для проведения онлайн-тестирования с использованием системы Moodle со следующими характеристиками:
- нагрузка на ресурс периодическая: в пиковые нагрузки - до 12 тыс. онлайн пользователей, в период простоя ~200 человек.
- проблема: в пиковые моменты сайт замедлял работу и падал. При этом недостатка в вычислительных ресурсах не было, а вот вопросов к архитектуре - множество.
- архитектура: 20 постоянно работающих серверов с разными базами данных в разных дата-центрах, где каждый сервер находился в регионе присутствия компании. Это огромная, неповоротливая архитектура, где для любого обновления нужно делать привязку к каждому отдельному серверу.
- подготовка сводной аналитики: данные раз в несколько дней выгружали из каждой базы данных и скриптами сводили вместе все отчеты.
- базы данных представляли собой модульную объектно-ориентированную динамическую среду обучения – Moodle.
Налицо неэффективная система обработки данных.
Заказчик столкнулся с проблемой перегрузки серверов и решил ее, просто увеличив количество серверов в 5 раз (хехе). Решение ожидаемо привело к расходам и сложностям со сведением данных с разных серверов в одну базу.
Далее кривая вывела заказчика к другой компании, которая создала множество инстансов баз данных и каждого отдельного Moodle, но проблему так и не смогли решить.
Тут, собственно, задача и попала к нам.
Задачи разработки
Основной запрос – оптимизация архитектуры ресурса. Мы предложили спроектировать архитектуру с динамически изменяемым количеством серверов в зависимости от нагрузки.
Ресурс должен быть представлен в виде единой базы данных, без деления по регионами, иметь единую систему отчетов и выдерживать пиковую нагрузку до 12 тыс. пользователей.
Итак: знаем что делать, но не знаем как. (пока)
Обратный отсчет
Для решения задачи наштормили несколько вариантов. Времени делать сложносочиненные решения не было…
Вариант 1: использовать Yandex Cloud (YDB) для создания отдельного программного модуля – коннектора, поддерживающего нативный интерфейс MySQL.
Для Moodle-системы это выглядело как подключение к базе данных MySQL, а коннектор транслировал запрос в YDB.
Сложности подхода: часть функций не поддерживалась, т.е. невозможно было реализовать полную совместимость с MySQL очевидными и быстрыми методами, из коробки. Нагрузочное тестирование показало слабые результаты. Показатели были существенно ниже обычных для MySQL.
От идеи быстро отказались и погнали дальше.
До сдачи 52 дня.
Вариант 2: использование оркестратора базы данных Vitess. Vitess был создан в 2010 году для решения проблемы масштабируемости MySQL, с которыми тогда столкнулась команда YouTube. Пиковая нагрузка превышала пропускную способность базы данных, а использование прокси-сервера между приложением и базой данных для маршрутизации и управления взаимодействием с базой данных позволило решить эту проблему.
Вдохновившись этой историей, мы попробовали взять в работу Vitess.
Ограничивающим фактором стало отсутствие адекватной документации. В результате тестирования получили схожие с первым вариантом результаты. Решение просто не стало работать в режиме кластера!
Мы обратились бизнес-поддержку YDB и выяснили, что и они тоже не работали с такими кейсами. Что ж, отрицательный результат – тоже результат.
До сдачи 41 день.
Настало время последнего варианта. Скажем прямо – на первый взгляд он выглядел так себе… Но, параллельно с работая над предыдущими вариантами, мы проводили ресерч и тесты и постепенно пришли к мысли, что при качественной проработке это может стать хорошим решением.
Лучшее - враг хорошего
Вариант 3: остаться на используемой базе MySQL в режиме кластера из одной ноды (экземпляра). Тут следует заметить, что предыдущий исполнитель, к которому обращался заказчик, решить такую задачу не смог. Он ушел с используемой заказчиком базы и создал множество инстансов баз данных и сервисов Moodle. Его подход, конечно, не нашел продолжения в новой архитектуре. Но идея с базой данной прижилась!
Нам удалось применить однонодовую конфигурацию кластера базы данных MySQL. Мы проверили ее оптимизацию и доработали конфигурации для работы с максимальной нагрузкой на ресурс.
Такой результат был получен за счет "тонкой" конфигурации кластера MySQL в соответствии с поставленной задачей, что позволило достигнуть требуемой пиковой нагрузки на одном экземпляре базы данных
Использовали Yandex Managed Service for MySQL® на базе инфраструктуры Yandex.Cloud в качестве платформы для управления кластером базы данных. Конфигурация сервера была следующая:
- CPU 96 ядер;
- RAM 192 ГБ;
- SSD 512 ГБ.
Создание централизованного хранилища
До сдачи 30 дней...
Исходная архитектура заказчика была примерно эры динозавров, поэтому мы провели миграцию всех структур и данных на современную контейнерную архитектуру. Но и тут появились проблемы, с которыми мы просели еще на неделю как минимум..
Проблема 1
После миграции перед нами встал серьезный вопрос о хранении данных, т.е. документов, изображений, внутренних файлов. Головоломка была в том, что с увеличением количества серверов мы не должны потерять скорость передачи этих данных.
Оптимизация и адаптация подразумевала необходимость централизовать хранилище, сведя все кластеры серверов в единую систему.
Проблема 2
Проблемой заказчика была трудоемкость работы с базами. Каждый сервер имел свой отдельный moodle, базу данных и файловые системы.
Чтобы свести все данные с каждого сервера использовались заклинания скрипты. Как понимаете, это приводило к хаосу. Идентификаторы связанных серверов пересекались и происходила перезапись данных.
Из хаоса в систему
Чтобы исключить подобные ситуации мы создали сетевое централизованное хранилище.
Хранилище имеет максимальную скорость чтения и записи до 8 Гбит/сек.Доступ к дисковому хранилищу организован через протоколы NFS (network file storage). Настроили RAID-массив и выделили хранилище в отдельный сервер, работающий на CentOS. После проведения тестирования мы перевели платформу на новый уровень порядка и организации и получили достаточно высокопроизводительное хранилище, которое гибко интегрировалось со всеми серверами.
Ищем равновесие
Системе был необходим дирижер динамической архитектуры. В его роли выступил балансировщик нагрузки (!!!), который при росте количества пользователей автоматически создает новые сервера, а при снижении – удаляет сервер через несколько минут после того, как нагрузка спала.
Мы использовали в проекте L7-балансировщик, что позволило в нагрузочном тесте сгладить итоговые результаты за счет поддержки функции Session Affinity, когда балансировщик запоминает пользователя и закрепляет его за определенным сервером бэкенда, что в свою очередь снижает нагрузку на файловый кэш.
По срокам мы вроде еще успевали, но нельзя недооценивать последние этапы.
Итоги
Еще около 12 дней ушло на развертывание сервисов, нагрузочное тестирование и ввод в эксплуатацию. Еще одна непредвиденная проблема и мы бы жестко пролетели со сроками. К счастью, ее не случилось.По итогу мы собрали пазл из разрозненных серверов в централизованный ресурс.
Для этого:
- провели централизацию базы данных;
- выполнили оптимизацию конфигурации кластера базы данных MySQL для работы с пиковой нагрузкой до 12 тысяч пользователей;
- вывели кэш сессий в Redis;
- использовали L7-балансировщик для распределения нагрузки между серверами;
- для хранения пользовательских временных файлов создали отдельный NFS-сервер, который может работать на скорости до 8 Гбит/сек.
Заказчик получил централизованную систему, единый Moodle, который может работать при максимальной нагрузке (см пикчу)
Решена проблема сведения результатов онлайн тестирования из разных баз: теперь данные отображаются в единой базе и администратору доступны сразу все отчеты.
По цифрам
Резко упала стоимость ресурсов в момент простоя платформы. Это главное.
Учитывая сезонность работы сайта, когда большую часть года ресурс работает с минимальной нагрузкой, и только несколько месяцев в году происходит резкий рост пользователей, методы балансировки нагрузки позволяют мощно сократить финансы.
Когда нагрузка отсутствует, ненужные сервера не запущены и заказчик за них не платит.
Расчет стоимости ресурсов идет в зависимости от нагрузки на сайт за 1 секунду.
Итого сервис располагает серверами:
- баз данных;
- файлового хранилища;
- сервисные сервера;
- сервера бэкенда;
- сервера-балансировщики нагрузки, которые создаются под обработку запросов.
Серверов-балансировщиков в пиковые нагрузки может быть до 24 шт. В момент простоя работают только сервер базы данных, сервер хранилища, сервер кэша и один сервер для обработки пользовательских запросов.Проведя изменения на материнской виртуальной машине необходимых нам данных по веб-интерфейсу, по формам, спискам мы устранили все танцы с бубнами и сделали ее единой точкой входа для всего кластера. Нагрузочное тестирование показало предельное RPS 200 (Requests Per Second – количество запросов за одну секунду). Цифра превзошла наши ожидания: для нашего проекта это эквивалентно работе 16 тысяч пользователей.
В итоге, Заказчик получил сайт 30 декабря. А мы ушли восстанавливаться :-)