Компания «Столплит» была основана более 15 лет назад и сегодня занимает лидирующее положение на мебельном рынке. Купить мебель «Столплит» можно не только через интернет, но и в фирменных магазинах в десятках регионов России и ближнего зарубежья. Сейчас их уже более двух тысяч.
Интаро осуществляет техническое сопровождение сайта с середины 2012 года.
Оптимизация серверной и программной части под высокие нагрузки.
Для ответа на этот вопрос в «цифрах» нужно провести аудит. Критичными показателями для нас на первом этапе аудита являются время генерации страницы на сервере и время рендеринга (отображения) в браузере. Хорошим суммарным показателем является время менее 1 секунды. Для простого аудита показателем «насколько все плохо» является суммарное время отображения страницы поделенное на 1 секунду.
Ниже приведен график Яндекс.Метрики, по которому видно, что у ресурса есть проблемы с производительностью. Время полного получения страницы может достигать 8 секунд. Есть большая вероятность, что пользователь не дождется открытия этой страницы и уйдет.
Еще одним немаловажным показателем является запас производительности, который можно получить, проведя нагрузочное тестирование на работающем проекте. Нужно иметь в виду, что целью нагрузочного тестирования является получение значения максимальной производительности, т.е. значений, при которых мы получим отказ в обслуживании. Именно поэтому нагрузочное тестирование нужно производить с особой аккуратностью, чтобы не допустить реального отказа в обслуживании. Обычно показателем нагрузочного тестирования является RPS (Requests per second) — количество запросов в секунду, которое способен обработать ваш сервер. Полученный показатель можно сравнить с текущим средним количеством запросов в секунду и получить доступный запас производительности вашего проекта.
Ниже приведен пример нагрузочного тестирования Яндекс.Танком. Тестирование проводилось на «боевом» проекте в час-пик. Видно, что RPS достигал значений близких к 30. Но фактический отказ в обслуживании начался с 17 RPS. Если принять во внимание среднюю нагрузку на сайт около 100 RPS, то можно считать этот запас критически низким, а сервис — потенциальной жертвой DDoS (атака, целью которой является отказ в обслуживании).
Обычно к таким последствиям приводит отсутствие или ошибки проектирования серверной архитектуры, или несогласованность работы разработчиков и системных администраторов. Как правило, над одним проектом могут работать разные команды разработчиков и даже системных администраторов. Но бывает и так, что проект заведомо разрабатывался под низкую нагрузку и к ее резкому скачку оказался просто не готов.
В любом случае никогда не поздно привести все в порядок. И хочу отметить, что как приведение к хаосу, так и установление порядка в проекте — это слаженный труд разработчиков, системных администраторов, контент-менеджеров и других специалистов. Именно поэтому нужно выделить узкие места проекта, разделить зоны ответственности и комплексно решать проблемы.
Существует поверье, что если купить достаточно мощный сервер, то можно перестать волноваться и забыть про апгрейд на ближайшие пару лет. Возможно это и верно для проектов со средней посещаемостью, не планирующих прироста пользователей на ближайшее время. Ведь на первый взгляд это удобно: оплачивать и администрировать 1 сервер. Но для проектов с высокой посещаемостью, с ее возможными всплесками это в корне не так.
Критически важным для таких проектов является время простоя во время технических работ и сведение к минимуму времени восстановления в случае аварии. Здесь применимо выражение «время — деньги». Именно поэтому нужно создать такую архитектуру, которая обеспечит нужный уровень отказоустойчивости и масштабируемости.
Рассмотрим каждый пункт подробнее.
Масштабируемость
Под масштабируемостью подразумевается способность быстро и просто добавлять вычислительные мощности в проект. Именно по этой причине нужно разделить серверы на выполняемые роли. Нужно четко понимать, что много «маленьких» серверов лучше, чем один «большой». Все серверы одной роли должны быть идентичной конфигурации. Это дает нам возможность для простого горизонтального масштабирования. В случаях отказа одного «маленького» сервера, мы имеем пропорциональную просадку производительности. В случае отказа одного «большого», мы скорее всего имеем отказ в обслуживании.
Если рассматривать типовой веб-сайт на PHP и СУБД MySQL, то разделение на роли примерно такое: балансировщик запросов, сервер приложения, сервер баз данных.
Балансировщик — сервер с Nginx на борту:
Сервер приложения — сервер, на котором выполняется бизнес-логика проекта. В нашем случае это код PHP. На сервере такой роли лучше использовать php-fpm вместо Apache, если нет прямых противопоказаний. Все-таки хороший веб-сервер у нас уже есть. Nginx очень хорошо справляется со своими обязанностями. Главная причина, по которой системные администраторы не спешат отказываться от Apache в качестве бекэнда на «живых» проектах — это наличие файлов .htaccess и, соответственно, куча реврайтов в них. Настоятельно рекомендую потратить время и переписать все реврайты под Nginx. Он делает это гораздо быстрее по своей природе.
Как уже само собой разумеющееся на сервере, выполняющем бизнес-логику должно быть много кэша. Кэшировать нужно все, что можно. У PHP должен быть OPcache или аналог. Использование memcaсhe в проекте всегда приветствуется.
Синхронизировать файлы проекта между серверами приложений можно любым удобным способом. Например lsyncd.
Забегу вперед и скажу, что на серверах приложений обязательно должен быть реализован функционал распределения нагрузки на БД.
Сервер баз данных — сервер с СУБД MySQL на борту. Рекомендую отказаться от использования чистой MySQL и посмотреть в сторону форков, таких как Mariadb и Percona. Для придания отказоустойчивости БД предлагаю посмотреть в сторону кластеризации. У чистой MySQL есть встроенный механизм реализации master-slave репликации. По сути, с его помощью можно реализовать master-master репликацию. Но советовать этого я не буду. Вместо этого предлагаю рассмотреть решение от Percona под названием percona xtradb cluster. Оно реализует настоящую master-master репликацию и полноценный кластер. К тому же он очень прост в управлении, масштабировании и восстановлении в случае сбоя, оснащен встроенным движком xtradb, полностью совместимым с InnoDB. К тому же есть возможность делать резервные копии, которые быстро восстанавливаются, причём гораздо быстрее обычного восстановления из sql дампа. А ребята из Mariadb разработали прекрасную утилиту maxscale для распределения нагрузки между серверами.
Отказоустойчивость
Главное правило отказоустойчивости — не допускать наличия единой точки отказа. Т.е. не допускать наличия недублированных узлов. Таким образом, серверов каждой роли у нас должно быть как минимум два. Что касается сервера-балансировщика, то его можно собрать в отказоустойчивый кластер или реализовать Round-robin DNS между несколькими балансировщиками.
По сути, реализуя схему с возможностью горизонтального масштабирования, представленную выше, мы получаем определенный уровень отказоустойчивости. Повышение уровня отказоустойчивости достигается дальнейшим горизонтальным масштабированием, добавляя серверы в нужную роль.
Безопасность
Безопасности много не бывает! Хочу остановиться на базовых моментах:
Для защиты от DDoS атак существует масса способов. Она может осуществляться на уровне хостинга. Некоторые маршрутизаторы обладают возможностью интеллектуальной обработки трафика и очистки его от «мусора». Обычно такая услуга предоставляется провайдерами на платной основе. Тюнинг ядра Linux может помочь устоять перед другими видами сетевых атак.
На примере реального проекта можно проследить, как описанный выше подход может привести в порядок даже очень запущенную систему.
Цель оптимизации
Задачей является крупный интернет-магазин мебели, построенный на CMS Bitrix.
Время генерации некоторых страниц на сайте достигало 200 секунд. Понятно, что при таких условиях пользователь никогда не дождется открытия страницы. Также на некоторых страницах количество запросов на хит достигало 20 000! На серверах, которым была отведена роль выполнения бизнес- логики, были установлены разные версии PHP интерпретатора. Была реализована master-slave репликация, но по факту балансировка не была реализована и работал только один мастер. Данный факт говорил о том, что деньги, выплачиваемые за аренду мощного сервера, не приносили никакой пользы. Серверы БД находились в ДЦ, удаленном от всех других серверов проекта, что накладывало задержку на время соединения более 10 мс. Memcached, установленный на мастер-сервере БД использовался только для хранения сессий, а весь кэш хранился в файлах.
Конфигурация серверов в начале
Парк серверов состоял из 5 довольно мощных машин. Под сервер, несущий на себе Nginx и выполняющий роль мастера для бизнес-логики, был выбран вариант с параметрами Dell PowerEdge R730, снаряженный Intel Xeon E5-2600 v3 2.10GHz Octa-Core, 128 ГБ DDR4 ECC RAM. Этот сервер обрабатывал 90% всех запросов и, судя по значению Load Average, должен был гореть ярким факелом от перегрева. Мастер и слейв БД MySQL находились в виртуальных контейнерах на 1 физическом сервере Dell PowerEdge R730. Как отмечалось ранее, слейв сервер просто реплицировал мастер и не нес никакой нагрузки, а значит ресурсы сервера, отведенные контенеру со слейвом попросту не использовались. Под слейв серверы, выполняющие бизнес-логику использовались две машины с параметрами Intel Core i7-4770, 32 ГБ DDR3 и, можно сказать, не справлялись со своими обязанностями. Также довольно мощный сервер использовался для простого хранения бекапов. На всех серверах использовались SATA диски 6 Гбит/с 7200 об/мин.
В конечном итоге на большинстве серверов не было задействовано и 10% доступных вычислительных ресурсов.
Что было сделано
Было решено использовать новый парк серверов и развернуть там новую архитектуру. После тестирования «переехать» на новые серверы, а от старых отказаться. Оптимальный выбор серверов под каждую роль смог сократить расходы на их аренду. Серверы получились дешевле используемых ранее. Проанализировав размеры данных проекта, было принято решение использовать SSD диски. Они быстрее SATA аналогов и заметно ускоряют файловые операции. Особенно это важно на серверах баз данных. Под хранение бекапов был выделен отдельный сервер-хранилище в соседнем ДЦ. Каждый сервер являлся физической машиной. Виртуализация не использовалась.
Тезисно остановимся на каждой роли:
Балансировщик
Серверы приложений
Серверы БД:
Все основные параметры серверов контролируются через систему мониторинга zabbix с оповещениями о нештатных ситуациях дежурному администратору. Параметры выполнения PHP контролируются через Pinboard.
Были переработаны нагружающие страницы и переписана часть компонентов системы. А в целом был проведен большой объем работы по оптимизации кода проекта.