Несколько лет назад, когда я знакомился с сервисом Amazon EC2 была заведена MicroInstance с Ubuntu 10.04 LTS на борту. На ней был поднят Apache и настроено несколько виртуальных хостов, включая блог на MODx Revolution. Выпала тут свободная минутка и подумалось мне, а что будет если на мой потаённый бложик вдруг набежит толпа читателей. Набегать ей в общем то неоткуда, но дух познания, привитый ещё в детстве многократными просмотрами киножурнала «Хочу всё знать», не давал покоя. Мне не доводилось пока участвовать в высоконагруженных проектах, поэтому было проведено небольшое исследование материалов в сети. Из блога в блог кочует утверждение, что необходимо отказаться от использования Apache в пользу Nginx. Это утверждение мне показалось странным, учитывая историю проекта Apache и сообщество разработчиков вокруг него. Неужели разработчики Apache не могут решить проблему ругаемого везде режима prefork? Так ли это на самом деле я и решил выяснить. О результатах читайте под катом.
Подготовка
Изучив тему более детально, выяснялось, что помимо MPM (Multi-Processing Module) prefork у апача также существуют модули mpm-worker и mpm-event, которые в одном программном потоке обрабатывают запросы от нескольких пользователей. Модули mpm-event и mpm-prefork связываются с php через fastcgi. Сравнить их работу c nginx и было решено.
Первым делом я решил посмотреть как поведёт себя Apache в режиме prefork при большом количестве запросов. Была запущена утилита siege с 40 потоками. Apache создал множество процессов и логи заполнились сообщениями о переполнении памяти. После чего сервер стал недоступен и пришлось делать terminate для данного инстанса, так как на reboot дождаться реакции в течении 5 минут так и не удалось. Был создан новый инстанс, к которому был подключен старый ebs. В итоге опытным путём было установлено, что на EC2 MicroInstance с её объёмом памяти в 630МБ оптимальными являются следующие настройки:
<IfModule mpm_prefork_module>
StartServers 3
MinSpareServers 3
MaxSpareServers 7
MaxClients 27
MaxRequestsPerChild 3000
</IfModule>
Теперь можно было нагружать сервер, не боясь потерять его управление.
Было решено протестировать следующие конфигурации:
- apache mpm-prefork с mod_php
- apache mpm-prefork с mod_php + nginx reverse proxy
- nginx с php-fpm
- apache mpm-worker с php-fpm
- apache mpm-event с php-fpm
В процессе тестирования пришла мысль, что ничто не мешает apache в режиме mpm-prefork работать с php-fpm и данная конфигурация также была добавлена в тесты.
О том, как установить используемые в этой статье конфигурации я рассказывать не буду, вы без труда можете найти данную информацию на просторах интеренета. Отмечу лишь, что во многих howto дублируется одна и та же ошибка для связки mpm-worker или mpm-event с php, а именно: в командах пакетного менеджера указано устанавливать пакет php5, на самом деле необходимо устанавливать пакет php5-cgi.
Меня интересовало прежде всего, какое количество запросов сможет выдержать вэбсервер. Поэтому я решил использовать для тестов утилиту siege. Поэксперементировав с JMeter, я пришёл к выводу, что он больше подходит для выяснения времени реакции на те или иные события. Таким образом, основной интересующий меня параметр из вывода результатов утилиты siege был Availablility. Исходя из этого, были подобраны параметры утилиты siege, чтобы Availability была менее 100%, но не слишком мала. На всех тестах использовалось количество потоков 20 (-c) количество повторений 20 (-r) режим benchmark (-b).
Для обработки результатов тестов был создан Excel файл, в таблицы которого вводились результаты выводимые утилитой siege. По результатам пяти тестов находится среднее арифметическое и среднеквадратичная погрешность среднего арифметического. Строится диаграмма Availability для разных конфигураций.
Был написан простенький скрипт, который выполняет необходимое количество тестов и обрабатывает результаты вывода siege для копипасты в Excel:
#!/bin/bash
n=1
touch tmp.out
while [ $n -le $2 ]
do
siege -b -q -c 20 -r 20 -i -f $1 >> tmp.out 2>&1
sleep 60
n=$(( n+1 ))
done
cat tmp.out | sed -nE '/Transactions/,/Shortest/p' | awk -F":" '{print $2}' | awk -F" " '{print $1}'| sed 's/./,/g' | xargs -L12 | sed 's/ /;/g'
rm tmp.out
Параметрами скрипта являются файл URL'ов, который генерировался из sitemap, и количество итераций в случае данных тестов всегда было равно 5. sleep 60 необходим для завершения всех очередей от предыдущей итерации.
По ходу было решено прицепить к сайту CDN CloudFlare, и, заодно посмотреть, как данный сервис влияет на нагрузочную способность вэбсервера. Для этого в DNS CloudFlare был добавлен субдомен с прямым адресом сайта и добавлен алиас в настройках виртуального хоста. Также был создан ещё один файл URL'ов для прямого доступа к сайту.
Результаты
Подробные результаты теста вы можете посмотреть в этом файле. Здесь я приведу только диаграммы.
Не понятно почему выделяется из общей тенденции apache mpm-prefork через CloudFlare.
Так как полученные результаты имели большие погрешности из-за значительного разброса значений каждого прохода, было решено провести дополнительный тест на локальной виртуальной машине. Для этого была создана гостевая система Ubuntu 10.04 LTS на VirtualBox, с параметрами идентичными EC2 MicroInstance (1vCPU,630MB,8GB). Чтобы получить похожий процент отказов, я ограничил максимальную загрузку процессора доступную виртуальной машине в 7% (Intel Core i7 2.8 ГГц). Подробные результату этого теста можете посмотреть в этом файле.
Соотношение результатов похоже на тест через CloudFlare.
Выводы
- Рекомендуемая во многих мануалах связка Apache и Nginx как reverse proxy, не пренесёт желаемого результата, еcли на вашем сайте мало статических ресурсов.
- Apache может успешно конкурировать с Nginx, если установить вместо модуля mpm-prefork модули mpm-worker или mpm-event.
- Apache может конкурировать с Nginx даже если вы используете модуль mpm-prefork, при этом необходимо использовать php-fpm через fastcgi.
- Если вы используете модуль mpm-prefork не забудьте ограничить количество процессов соответственно ресурсам вашей системы.
- Использование CDN CloudFlare на бесплатном тарифе не даёт ощутимого увеличения нагрузочной способности. Плюсом можно считать, что в случае полной недоступности сайта CloudFlare выдаст сохранённый «снимок» запрашиваемой страницы.
Автор: Shkurenkov