Почему FastCGI + Nginx быстрее, чем Apache + mod_php

Сначала я собирался написать пост о том, почему Nginx в связке с FastCGI работает быстрее, чем Apache с mod_php. Не так давно ходили слухи, что Nginx с запущенным PHP через FastCGI производительнее, чем Apache с mod_php. Многие знакомые утверждали, что это чистая правда. Некоторое время назад я провел небольшое исследование по этому вопросу и собрал интересные факты.

Сегодня я хотел бы подробно рассказать о своих поисках истины и проанализировать получившиеся результаты. Так вот, для начала замечу, что раньше мне приходилось увеличивать производительность. Если мне не изменяет память, это было необходимо и для работы с Magento.


Для тестирования я сделал простенький скрипт «привет, мир». Почему такой простой? Потому что когда вы работаете с интерпретатором PHP, не должно быть никакой разницы в производительности. Тогда почему не сделать пустую страницу? Потому что для чистоты эксперимента необходимо обеспечить двустороннюю связь. Моей целью было проверить пропускную способность веб-сервера, а не PHP. Так что я потратил минимум времени на PHP и все внимание уделил проверке передачи данных.
Базовые тесты показывают следующее:

Apache + mod_php

Total transferred: 3470000 bytes
HTML transferred: 120000 bytes
Requests per second: 2395.73 [#/sec] (mean)
Time per request: 4.174 [ms] (mean)
Time per request: 0.417 [ms] (mean, across all concurrent requests)
Transfer rate: 811.67 [Kbytes/sec] received

NginX + PHP-FPM

Total transferred: 1590000 bytes
HTML transferred: 120000 bytes
Requests per second: 5166.39 [#/sec] (mean)
Time per request: 1.936 [ms] (mean)
Time per request: 0.194 [ms] (mean, across all concurrent requests)
Transfer rate: 801.82 [Kbytes/sec] received

Apache обрабатывает 2400 запросов в секунду, по сравнению с 5200 запросами которые за то же время обрабатывает Nginx. Этот показатель вырос. Чтобы разобраться, я запустил отладочный режим для Apache с ключами -с и -f. Ключ -c показывает суммарное время на системные вызовы, ключ -f отслеживает форки. В результате мы получили вот что:

% time seconds usecs/call calls errors syscall
— — — — — — 33.65 0.042063 4 10003 getcwd
16.10 0.020127 2 10001 writev
16.00 0.019994 2 10001 shutdown
10.54 0.013179 0 51836 40118 open
9.01 0.011263 1 20008 semop
5.22 0.006522 0 54507 10002 read
2.53 0.003158 0 10024 write
1.91 0.002386 0 88260 66483 close
1.57 0.001959 245 8 clone
1.16 0.001455 0 54832 384 stat64

getcwd? Почему? Я вспомнил, что я оставил опцию AllowOverride в. Htaccess включенной. Так что я снова протестировал систему, но уже поменял значение AllowOverride на None.

Total transferred: 3470000 bytes
HTML transferred: 120000 bytes
Requests per second: 5352.41 [#/sec] (mean)
Time per request: 1.868 [ms] (mean)
Time per request: 0.187 [ms] (mean, across all concurrent requests)
Transfer rate: 1813.40 [Kbytes/sec] received

Получается, что Apache со своими 5352 запросами в секунду опережает Nginx. Но что делать, если надо передать больше данных? Я увеличил размер данных и провел повторное тестирование.

Apache

Total transferred: 1051720000 bytes
HTML transferred: 1048570000 bytes
Requests per second: 2470.24 [#/sec] (mean)
Time per request: 4.048 [ms] (mean)
Time per request: 0.405 [ms] (mean, across all concurrent requests)
Transfer rate: 253710.79 [Kbytes/sec] received

NginX

Total transferred: 1050040000 bytes
HTML transferred: 1048570000 bytes
Requests per second: 2111.08 [#/sec] (mean)
Time per request: 4.737 [ms] (mean)
Time per request: 0.474 [ms] (mean, across all concurrent requests)
Transfer rate: 216476.53 [Kbytes/sec] received

В этом случае опять можно заметить преимущество веб-сервера Apache. Смысл заключается в следующем. Apache имеет встроенный интерпретатор mod_php, что и позволяет ему работать быстрее. Поэтому, если вы используете только PHP, Apache — лучший выбор для повышения производительности. И если вы вдруг наблюдаете значительную разницу в производительности, то вы должны проверить, включена ли опция AllowOverride. Если это так, попробуйте поменять значение в httpd.conf и повторите попытку.

Если вы работаете с разным содержимым, добавляете CSS, JS, изображения, тогда Nginx обеспечит лучшую общую производительность, но он не будет работать быстрее PHP. Также, Nginx будет лучше реагировать на атаки типа отказа в обслуживании, но, как правило, на снижение риска такого рода направлен сервис CDN.
Таким образом, если вы работаете с чистым PHP, Apache остается для вас самым эффективным решением.

Для статики нужен nginx. Он стал уже стандартом. Тут же сравнение быстродействия php, через mod_php апача или как fast cgi. Я считаю, что апач нужен когда есть какой-то нетривиальный функционал на стороне сервера. Апач имеет безграничные возможности благодаря бесчисленному количеству модулей. Пруф httpd.apache.org/docs/2.2/mod/. Другое дело, что nginx умеет 99% всего, что нужно современному рынку для продуктивной работы. Но он не так хорошо изучен бородатыми апач-админами.

nginx с php-fpm общался через порт или сокет? у меня через сокет получалось в два раза быстрее, чем через порт. так что может в этом быть дело.

К сожалению, в статье конфиги не приводятся. Сокеты всегда быстрее работают (нет задержки отправки пакетов tcp). Только когда сервера расшардены на разные машины, сокеты использовать не выйдет.

ну так и apache+mod_php на разных машинах не предусмотрен вроде как ?
подразумевается, что локальная связка же.

Это как раз основной минус апача. Мод пхп — это модуль апача. Они не разделимы. Nginx+php-fpm — легко шардится. Nginx (почти во всех видах конфигов) выступает в роли балансировщика, а под пхп может быть выделено несколько разных инстансов для обработки запросов (если выполняются какие-то трудоемкие скрипты).