Почему NginX с Fast-CGI быстрее, чем Apache с mod_php?

http://www.eschrade.com/page/why-is-fastcgi-w-nginx-so-much-faster-than-apache-w-mod_php/
  • Перевод
Недавно я слышал, что NginX, работающий с PHP через FastCGI был быстрее Apache с mod_php. Я также видел, что люди как отрицают, так и соглашаются с этой гипотезой.  Давайте проведем небольшой тест и узнаем показатели работы этих систем.

Для тестирования я создал небольшой Hello world скрипт.  Почему я не выбрал что-то посложнее?  Ответ прост: в интерпритаторе 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 запросов в секунду в отличии от Nginx. Он справился с 5200 запросами.  Такого большого количества я раньше никогда не видел. Я выполнил те же запросы с -c -f для Apache, чтобы узнать причины такой разницы.  -c отображает время системных запросов, -f следует ответвлениям.  Какой же результат для первых 10 строк?

% 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?  Но почему?  После я вспомнил, что у меня активировано AllowOverwrite (.htaccess).  Выполнил те же тесты после отключения этой функции.

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


С 5352 обработанными запросами Apache опередил NginX.  Но что же произойдет тогдпн, когда объем передаваемых данных увеличится?  Я создал около 100k контента и попробовал снова.

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


В этот раз разница была заметнее.  Ощущаются некие изменения. PHP встроен в  mod_php Apache, что должно ускорять его.  Если на Вашем сервере работает только PHP, то это должно быть лучшим решением в плане производительности.

Если Вы работаете с разными языками вроде CSS, JS и изображениямм, тогда Вам больше подойдет NginX. Его производительность будет выше, но PHP быстрее не станет.  Он также будет надежнее в плане защиты от DDoS, но CDN по-прежнему является лучшим решением.

Ниже представлены графики для сравнения производительности:

Поделиться публикацией
Комментарии 35
    +3
    PHP встроен в mod_php Apache, что должно ускорять его.

    Откуда такие выводы?
      0
      Хорошо, а как тогда можно сформулировать?
        +1
        Apache+mod_php ускоряется относительно Apache + PHP-CLI over CGI, конечно же.
        С mod_php не поднимается каждый раз конфигурация и окружение php на каждом запросе. Только в момент запуска Apache. Так же все включенные в конфигурации расширения так же не подгружаются на каждый запрос (ну за исключением dl('extenstion') ).
        По поводу .htaccess и AllowOverride было написано еще в древней книжке o'reilly «Тюнинг Веб-сервера». Все что нужно в .htaccess лучше перетащить в конфиг и включать AllowOverride только там, где это необходимо через конфиг. Ибо разрешение его с DocumentRoot будет вести к полному перечитыванию ВСЕХ вложенных папок (удовлетворяющих запросу) по пути для поиска .htaccess.
        Особенно это будет адово тормозить, если в папке с AllowOverride All (и .htaccess соответственно) лежит пара тысяч файлов на одном уровне.
          +1
          тут, кроме htaccess естьеще многоопределяющих факторов… например — дефолтные конфиги, сколько было запущено вокеров у апача и фпм-а? Как была настроена связь nginx-php (к бабке не ходи, а через unix сокет — будет быстрее)?
            0
            Через unix сокет будет скорее всего чуть быстрее, чем через реальный ip подвешенный на физический ethX. Это понятно.
            Но не факт что сильно быстрее, чем через loopback interface. Помнится была тема (не знаю насколько реализована), что в Linux можно пакеты идущие через lo пулить мимо роутинга и netfilter
            Только вот Apache вроде не умеет на сокете работать (если цеплять его backend'ом к nginx), так что для одинаковых условий в любом случае надо оба тестить на loopback или реальной сети
              0
              Очень было бы интересно узнать как это сделать «пакеты идущие через lo пулить мимо роутинга и netfilter». Я только нашёл как убрать NOTRACK
        +4
        … а теперь запускаем все запросы не подряд, а одновременно, и...
        Nginx всегда славился количеством соединений, которые он может одновременно удерживать, в том числе медленных, скоростью отдачи статики, и объемом потребляемых при всем этом ресурсов. Но для меня всегда было очевидно, что php будет работать примерно с одинаковой скоростью независимо от того, на каком сервере он запущен.
          0
          Я же явно сказал, что PHP не ускорится, зато при смешении языков разница в производительности появится.
            +2
            Да, вы сказали об этом явно. Но в целом статья, не смотря на попытку маскировки под исследование, оказалась капитанской. Доказываемые в ней утверждения, я считаю, не требуют доказательств.
              +2
              Причем тут «смешении языков»? Попробуйте повторить тест на 1000 медленных соединений. =)
              И да, бенчмарк без единого конфига и описания методики — это убедительно.
                0
                Про бенчмарк спасибо. Виноват, исправлюсь :)
            +3
            нужен третий вариант
            nginx+apache ;)
              +11
              и к черту этот PHP
                –2
                Что предложите взамен?
                  +2
                  В том числе, собственно почему нет?
                  Вообще почти любой ЯП через cgi и в путь!
              0
              В этом случае будет сравнение
              Nginx + PHP-FPM vs Nginx + (Apache+mod_php).
              В итоге «медленные» запросы будут так и так рулиться nginx'ом. А mod_php и php-fpm сравнимы по скорости (все равно «под капотом» одно и тоже)
              +2
              В первую очередь в сравнение apache и nginx нужно сравнивать модель обработки запросов. А между apache mpm_prefork (именно он используется при mod_php) и nginx разница огромна уже в самой идеи.
                –6
                Поэтому чаще всего и используют апач для скриптов и nginx для статики
                  +6
                  Методика тестирования никуда не годится. Конфигурации железа нету. Ниочем.
                    0
                    разница будет весьма и весьма небольшая. потому что сравниваются по факту два prefork-сервера.
                      0
                      Это вы на какой комментарий ответили? И откуда взялся второй prefork-сервер?..
                        +1
                        это я комментарий к статье оставил :)

                        php-fpm — это вполне себе prefork-сервер: по процессу на запрос. кроме того, умеет спавнить воркеров on demand.
                      –5
                      сравнение из разряда «кто сильней — слон или кит». и, как тут уже написали, не представлен третий вариант: nginx в качестве frontend с apache+mod_php в качестве backend.
                        –3
                        По мне статья не полная, если в ней не указан hhvm. На сколько вырастет производительность если использовать Apache + hhvm и для статики Nginx?
                          +3
                          Какое-то сравнение серверов в вакууме. Ни тебе потребления ресурсов, ни конфига железа…
                            +1
                            А не достаточно того что оба теста проводились на одном и том же сервере? Конфигурация железа будет играть большую роль?! Если вы возьмете топовый 4-х процессорный сервер, с тонной оперативки или возьмете E3-13XX с 8-16гб на борту разница по запросам все равно составит ~5%

                            ЗЫ Если не прав, поправьте.
                              +1
                              Ну, к примеру, результаты теста сильно зависят от соотношения сетевых задержек при обмене данными между клиентом и nginx — и между nginx и php-fpm. Если nginx и php-fpm запущены на одном сервере, то важно, тестовый клиент находится на том же сервере — или все-таки между ними есть какое-то расстояние.
                                0
                                Даже если между сервером на nginx и клиентом есть расстояние, то между апачем и клиентом точно такое же расстояние, этого требуют условия тестирования, иначе глупо сравнивать два сервера с разными клиентами, результат будет искажен. По поводу задержек между нгинХ и пхп-фпм, думаю что схема построена через сокет, тк иначе тест с апачем так же будет не корректен. Можно еще конечно целое облако пхп-фпм'ов нагородить и сравнить с одинм сервером апача, или облако апачей, а первый как проксирующий апач, но это уже фарс, думаю что все это понимают.

                                Так что я, читая статью, представлял себе, что конфиг сервера с апачем равен конфигу сервера с нгинХ+пхп-фпм, расстояние до клиента — одинаково, и все компоненты обоих софтверных серверов располагаются на одном физическом сервере, под одной и той же операционной системой, на которую поставлены из нулевого состояния. (на чистую систему)
                                  0
                                  Дело не в том, одинакого расстояние до клиента — или нет. А в том, есть ли оно вообще. Сейчас nginx вроде как проигрывает апачу 15%. Но если брать реальную ситуацию (клиент находится далеко), эта цифра должна уменьшиться.
                                    0
                                    Я сам приверженец связки NginX + php-fpm, она мне как-то больше нравится, да и облако их пхп-фпм'ов легко наращивать, я согласен с вами что при реальном использовании разница может сократиться в разы, но как мы все понимаем это зависит от клиентов и их каналов до нашего сервера. NginX считается более легковесным при отдаче статики, а пхп обрабатывается php-fpm, как правильно заметили выше, скорость пхп не меняется в зависимости от обвязки, а накладными расходами можно пренебречь, тк они что там, что там будут примерно одинаковы, а если учесть что фпм и нгинХ в большинстве случаев разносятся по разным серверам и облако фпм-ов можно наращивать, то на мой взгляд запариваться из-за лишних 5% производительности, в сравнении с удобством масштабирования — может кому — то хочется, но не мне.
                                    +2
                                    Ключевой момент тут ещё в том, а как общался nginx с php-fpm.

                                    Apache с php общался напрямую в памяти. Если при этом nginx был настроен слать в php всё по tcp, да ещё и без keepalive, то уже неравные условия. Плюс имеют значение настройки размеров буферов для приема ответа, количество рабочих процессов с php, если у apache было 100 рабочих процессов, а у php-fpm было 10, то опять условия неравные. И как эти процессы запускались, заранее или ondemand.

                                    Потом настройки логгирования, а они были одинаковы? Когда тест состоит из выдачи «Hello world», то write() одной строчки в файл уже вносит заметную задержку.

                                    Ну и вообще любые цифры без указания погрешности — это ложь. Любые результаты и выводы, без исследования первопричины — бесполезны, поскольку ни чем не подкреплены, кроме субъективного впечатления автора от своих тестов, на конкретно своей системе, в своей конфигурации, которую он к тому же не приводит. Всё это не воспроизводится. Вот человек тоже провел тесты и намерял наоборот, nginx+php-fpm чуть быстрее: systemsarchitect.net/apache2-vs-nginx-for-php-application/
                                      0
                                      Про процесс тестирования писал выше, при прочтении статьи рассчитывал что кол-во воркеров, как и коннект были идентичны, логи отключены, либо пишут одинаковую инфу, воркеры запущены заранее и там и там. Но это мои догадки, основанные на дефолном конфиге Nginx+php-fpm. Можно перейти к детальному анализу не только конфигов фпм-а но и php.ini, я считаю что все конфиги были стоковыми или подогнаны под конкретную задачу, в следствии чего были идентичными, а считаю так, потому, что нет обратной информации.

                                      ЗЫ не претендую на истину, все выше изложенное есть мое мнение и не более.
                                      ЗЗЫ Можно долго гадать что там было и как тестировалось, давайте исходить из того, что все конфиги были по большей части дефолтными, немного подогнанными друг к другу для чистоты тестов.
                                        +1
                                        Если конфиги были стоковыми, то, как минимум, количество рабочих процессов fpm и апача различалось в разы. Ну и если под стоковым nginx+php-fpm конфигом понимать закомментированные строчки из nginx.conf по умолчанию, то да, там tcp:

                                                # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
                                                #
                                                #location ~ \.php$ {
                                                #    root           html;
                                                #    fastcgi_pass   127.0.0.1:9000;
                                                #    fastcgi_index  index.php;
                                                #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
                                                #    include        fastcgi_params;
                                                #}
                                        


                                        Можно перейти к детальному анализу не только конфигов фпм-а но и php.ini, я считаю что все конфиги были стоковыми или подогнаны под конкретную задачу, в следствии чего были идентичными, а считаю так, потому, что нет обратной информации
                                        Мой опыт общения с подобными «исследователями» и «исследованиями» подсказывает, что скорее всего ровно наоборот — буквально всё было сделано неправильно.
                                          0
                                          Я скорее про конфиг Фпм-а говорил, который по умолчанию работает на сокете, в nginx-е его надо менять… Я писал что конфиги немного подгоняются друг под друга, но видимо этот момент проигнорирован. Дальнейшую дискуссию предлагаю закончить, тк можно привести кучу доводов за и кучу против, все равно каждый останется при своем мнении.)

                                          Мой опыт общения с подобными «исследователями» и «исследованиями» подсказывает, что скорее всего ровно наоборот — буквально всё было сделано неправильно.

                                          Не исключено.

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое