Сама по себе инструкция о том, где что подкрутить на сервере, чтобы Drupal стал работать быстрее, встречаются на просторах интернета в разной степени детализации. Однако все встречавшиеся мне статьи обладали небольшим изъяном: я не встречал каких-либо реальных замеров, сопутствовавших настройке. Как численно меняется скорость генерации страницы? Как меняется использование памяти? Что происходит при увеличении количества параллельных запросов? Давайте проведём эксперимент. Некоторые рекомендации, изложенные в статье, носят общий характер и могут быть полезны для других CMS.
Вместо предисловия
В основу данной статьи легла подборка материалов Server tuning considerations, размещённая на официальном сайте Drupal. Из неё отобрано то, что носит наиболее универсальный характер и может быть применимо к произвольному серверу, на котором планируется использование Drupal (в частности, секции, касающиеся настройки PHP и MySQL). Эта статья не охватывает вопросы тонкой настройки самой CMS.
Экспериментальная модель
Для проверки нагрузки был создан некий эталонный тяжёлый сайт. Для этого был использован Drupal 7 и несколько популярных модулей, в том числе Views и Pathauto. В один из типов материала было добавлено числовое поле, которое могло принимать значение от 1 до 10. С помощью функции генерации контента модуля Devel было создано около 10 тыс. страниц материала данного типа и от 0 до 15 комментариев к каждому посту.
Далее был создан и размещён на главной странице блок Views, выбирающий 100 случайных страниц, где поле принимало значение 5 (т.е., если верить теории вероятности, 100 из 1000 страниц) вместе с комментариями к ним. Критерий фильтрации Global: Random был использован, чтобы страница гарантированно генерировалась по-новой при каждой загрузке. На личном тестовом сервере время генерации такой страницы составляло примерно 10 секунд. Также при подготовке был поднят тестовый интернет-магазин на базе Commerce Kickstarter и сгенерировано около 5 тыс. товаров. Однако выяснилось, что Global: Random совершенно не дружит с Search API, а без рандомизации страница с 96 продуктами грузилась ощутимо быстрее, чем предыдущая тестовая страница. Потому замеры по быстродействию интернет-магазина не проводились. Тестовые сайты были перенесены на…
Экспериментальное оборудование
Для экспериментов я позаимствовал на несколько дней свежеустановленные VPS Intel Xeon E3-1230 3.2GHz / 2-3 GB RAM / 30 GB SSD и Intel Xeon E3-1230 / 8GB DDR3 / 4x1TB SATA2 / 100Mbps Unmetered в Нидерландах (далее по тексту —
Данные «сырого» сервера
Первый замер был произведён до начала какой-либо оптимизации. Собственно, в этих замерах я остановился на 40 параллельных запросах. Полученные результаты выглядят примерно так:
На этом и последующих аналогичных графиках по оси X будет доля запросов, которые были обслужены за время, не превышающее соответствующего значения по оси Y.
Кроме того, интереса ради я запустил бесплатный тест Loadimpact, однако какой-либо ощутимой нагрузки он не создал.
Оптимизация PHP
Первое, что нужно сделать на сервере под Drupal, — выставить в php.ini значение memory_limit хотя бы 256M. Как правило, этого совершенно достаточно для большинства сайтов. А вот 128M порой оказывается маловато. Впрочем, это нельзя назвать оптимизацией, это скорее жизненная необходимость.
Для ускорения работы сайтов на уровне PHP разработчики рекомендуют использовать различные кеширующие оптимизаторы. В других источниках чаще всего упоминается APC, потому к нему я и обратился. О том, как его поставить, можно почитать в инструкции. Сейчас же нас интересуют ключевые параметры настройки. Собственно, основной параметр — размер сегмента памяти кеша, apc.shm_size. Чем более грузная страница, чем больше различных файлов подключается при исполнении, тем больше должно быть значение. Например, тестовому сайту хватило 64M. А тестовый магазин при этом значении выдал ошибку:
[Mon Jan 13 21:41:46 2014] [error] [client 176.36.31.190] PHP Warning: Unknown: Unable to allocate memory for pool. in Unknown on line 0, referer: http://s2shop.1b1.info/products?page=2
Поднятие значения до 256M вмиг убрало эту проблему. По данным модуля Devel, при разовых просмотрах сайтов включение кеширования повлияло на такие параметры:
- в полтора-два раза сократилось время генерации страницы;
- сократилось пиковое потребление памяти с примерно 50-55 MB до 30-32 MB для тестового сайта и с примерно 65-70 MB до 30-32 MB для тестового магазина.
О том, как повлияло включение APC на результаты бомбления с помощью ab, будет сказано немного позже. По общедоступной публичной информации, замечательные результаты даёт использование php-fpm вместо Apache + mod_php. Однако я пока не пробовал сравнивать эти две конфигурации.
Оптимизация MySQL
Один из самых простых способов оптимизировать MySQL — заменить my.cnf на my-huge.cnf. Этот файл рассчитан на системы с достаточным (2 Гб и выше) количеством оперативки и масштабным использованием MySQL. Помимо всего прочего, от стандартного конфига он отличается существенно большим размером буфера (key_buffer_size) и включением кеширования запросов (query_cache_size).
Общее изменение скорости отдачи при последовательном применении выглядит примерно так.
Е3-1230, 10 параллельных запросов
Е3-1230, 30 параллельных запросов
Как можно заметить, на
E3-1230, 50 параллельных запросов
Как видим, на сервере с SATA дисками буферизация с кешированием очень быстро начинают захлёбываться. При этом на
Тесты LoadImpact
Проведённые с помощью утилиты ab тесты показывают не реальную загрузку страниц сайта, а скорее качественное изменение производительности. Для каких-то более приближённых к жизни данных я провёл пару тестов с помощью Loadimpact.
- На главную страницу тестового сайта были натравлены до 100 SBU, примерно равномерно распределённых по 5 разным локациям (2 в США, 2 в Европе, 1 в Австралии). Суммарный график не позволяет увидеть, напрягла ли сервер эта нагрузка хоть сколько-нибудь.
Но возрастание нагрузки становится заметнее, если смотреть графики сугубо по европейским точкам, с которыми связность лучше.
При этом общий поток данных был близок к 90 Мбит/с. Хотелось догнать канал до полочки, но не осталось кредитов.
Нагрузка на процессор становится заметной, однако Load average не идёт ни в какое сравнение с тестами ab.
- В заключение я склонировал обычный небольшой информационный СДЛ и натравил на него Loadimpact из 8 разных точек. Все точки тестирования обращались к разным страницам сайта. За 10 минут количество SBU также дошло до 100.
Отдача была весьма равномерной, без каких-либо явных замедлений.
При этом сервер этого теста практически не заметил.
Вместо заключения
Я рассмотрел влияние на скорость работы сайта всего двух существенных параметров, потому буду благодарен всем, кто сможет дать дополнительные полезные советы по затронутой теме. Кроме того, где-то дней 5 после публикации тестовые среды ещё будут оставаться живы, и если у Вас есть ещё какие-то рекомендации по оптимизации или предложения по тестированию, я постараюсь за этот период воплотить их в жизнь и добавить в статью. Призываю всех обмениваться собственным опытом оптимизации и своими хитростями. И спасибо, что терпеливо дочитали.
Автор: Vasiliskov