Nginx + PHP-FPM против Apache2 Prefork + mod_php

    Все началось с этой темы на форуме, когда многие на полном серьезе стали рассуждать, мол, nginx совсем не быстрее Apache, и даже перевод документации с официального сайта был неубедителен. Как известно, нет ничего более приятного, чем провести тестирование и показать график для привлечения внимания. Вот например график по обще нагрузке на сервер, попробуйте угадать где тут этап тестирования Nginx, а где — Apache.
    image
    Ну а перед тем как узнать правильный ответ — немного про сервер и механизм тестирования.
    Дабы исключить всякие подозрения на «подкручивание» своих VDS, тест проводился на стороннем сервере, любезно предоставленным мне для теста одним из участников форума вот в такой кнофигурации:
    AMD Athlon X2 5600+ 4 GB DDR2 2×400 GB HDD с Linux Debian в минимальной установке. Весь софт устанавливался стандартным образом — через apt-get. И PHP и Apache ставились в минимальном режиме.
    Для объекта тестирования я поставил очень легкий блог Moscquito, который работает без MySQL, написав туда пару постов и камменты.

    Прежде всего хочу сказать что перед запуском бенчмарка Nginx и Apache я перезагружал сервер. Сетевая подсистема была немного подкручена для более быстрой работы:
    sysctl -w net.core.rmem_max=16777216
    sysctl -w net.core.wmem_max=16777216
    sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
    sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"
    sysctl -w sysctl net.ipv4.tcp_window_scaling=1
    sysctl -w sysctl net.ipv4.tcp_timestamps=1
    sysctl -w sysctl net.ipv4.tcp_sack=1
    sysctl -w net.ipv4.tcp_no_metrics_save=1
    sysctl -w net.ipv4.tcp_moderate_rcvbuf=1
    sysctl -w net.core.netdev_max_backlog=1000
    sysctl -w net.ipv4.tcp_congestion_control=htcp
    sysctl -w net.core.somaxconn=1000
    ifconfig eth0 txqueuelen 1000

    И повышались лимиты для корректной работы тестируемых и самих бенчмарков:
    ulimit -s unlimited
    ulimit -n 1024000

    Для обоих веб-серверов был установлен таймаут в 300 секунд (стандартный для Apache, в Nginx он меньше).

    PHP-FPM

    Процессы были привязаны к TCP сокету, создано два пула по 4 процесса в каждом в статичном режиме.

    nginx

    Два воркера по 10240 коннектов каждый, php подключен как апстрим:
    upstream php {
    server 127.0.0.1:9000 max_fails=1 fail_timeout=60s;
    server 127.0.0.1:9001 max_fails=1 fail_timeout=60s;
    }


    Apache

    Отключен Keepalive, а MaxClients и ServerLimit установлены в 10240

    Теперь о бенчмарке


    Я постарался создать ситуацию сайта под DDOS атакой, когда 20k ботов долбят в главную страницу, а 5000 легальных пользователей ходят по сайту.
    Импровизированную DDOS-атаку легко можно при помощи ab. А вот для пользователей пришлось сгенерировать карту сайта и натравить на нее siege.

    Тестирование занимало час и запись о доступности сайта логгировалась с помощью ab. Вот какие две команды я паралельно запусал в screen'е:
    while true; do ab -r -t 300 -n 20000 -c 20000 213.239.211.15 >> nginx.log; sleep 5; done

    while true; do siege -i -f urllist.txt -c 5000 -b -t1M ; sleep 5; done


    Естественно, что для бенчмарка с апачем лог писался в apache.log

    Перейдем к графикам


    image
    Как видно — число процессов изменялось только во время работы Apache, ну так недаром его MPM назвали Prefork. Nginx и PHP-FPM статичны, в чем их большой плюс.

    image
    К сожалению график памяти получился не очень красивым, но если посмотреть внимательно — памяти Apache потребляет больше.

    image
    image
    Графики переключений между процессами и их форк очень интересно коррелируют между собой.

    image
    Раскладка по утилизации CPU тоже явно не в пользу Apache.

    Пробьем по логам


    Nginx:

    # grep -c Failed nginx.log 
    38
    # grep  Failed nginx.log | grep -v 'Failed requests:        0'
    Failed requests:        10629
    


    Расшифровка — за час работы связка Nginx+PHP-FPM успела пройти 38 итераций и завалить одну из них — 10629 ошибочных запросов. Это было связано с недоступностью апстрима — siege постарался, запустив большинство запросов на главную страницу.

    Apache:

    # grep -c Failed apache.log 
    23
    # grep  Failed apache.log | grep -v 'Failed requests:        0'
    Failed requests:        8730
    Failed requests:        2124
    Failed requests:        10539
    Failed requests:        7599
    Failed requests:        6027
    Failed requests:        1986
    Failed requests:        7578
    Failed requests:        270
    Failed requests:        9819
    Failed requests:        60
    Failed requests:        9369
    Failed requests:        8193
    Failed requests:        10248
    Failed requests:        684
    Failed requests:        7968
    


    А вот с Apache все плохо — даже если вычеркнуть 2 «удачных» попадания siege, то остаются еще ошибки + за отведенное время было выполнено меньше запросов.

    Таким образом, по результатам тестирования связка Nginx+PHP-FPM побеждает Apache со счетом 38:23
    Поделиться публикацией

    Похожие публикации

    Комментарии 95
      +3
      Пока хостер не выключил сервер — можете его подрюкать.
      Сам москит тут: 213.239.211.15/ — можете его через ab, или написать там пару комментов.

      Статистика мунина тут — 213.239.211.15/munin/localdomain/localhost.localdomain.html
        +5
        Респект за топик, хоршее доказательство. Но nginx может еще больший прирост давать.
        С апачем сравнивать нгинкс — это как жопу с пальцем…
          +1
          Многие этого незнают
            0
            Это их беда. И наше счастье. :)
            +3
            Все-таки да, здесь php получился почти не при чем, так как основное влияние на результаты теста оказывает nginx vs apache, а не mod_php vs php-fpm. И если поставить между клиентом и сервером еще и медленный канал, апач проиграет с разгромным счетом из-за кучи долго отдающихся данных.

            Если я правильно понимаю, возникшее там непонимание :) касалось выигрыша, который дает nginx + php-fpm по сравнению с nginx + apache/mod_php. Он и правда должен быть не такой большой.
              0
              >Если я правильно понимаю, возникшее там непонимание :) касалось
              >выигрыша, который дает nginx + php-fpm по сравнению с nginx +
              >apache/mod_php. Он и правда должен быть не такой большой.

              Мне тоже казалось, что это именно так — как ТС пришло в голову что вопрос в apach vs nginx — загадка.
                0
                php-fpm более производительный, чем mod_php в prefork. Ибо тред менее жруч чем форк.
                  +1
                  А откуда треды взялись в php-fpm?
                    –1
                    php-fpm это надстройка над fastcgi php, fastcgi php — это треды.
                      –1
                      > fastcgi php — это треды

                      ничего подобного
                    0
                    Это и так понятно, что тред менее жруч, чем процесс. Так зачем было сравнивать штуку, которая делает процессы, со штукой, которая делает треды? Если я правильно понял, что такое php-fmp (дела не имел с ним), то его стоит сравнивать с mpm_worker, а вовсе не с mpm_prefork.
                      0
                      2 разных sapi php, 2 разных метода обработки соединений веб-серверами, я бы на apache2 worker + zts php посмотрел
                        +1
                        zts не имеет нужных расширений и иногда сегфолтит
                    0
                    Да тут у Андрея вообще странные условия теста… Выигрыш будет скорее всего в пределах погрешности всяких там колебаний.
                  0
                  Желательно еще обращатся к пхп через сокет, мне кажется это будет немного быстрее.
                  • НЛО прилетело и опубликовало эту надпись здесь
                      +1
                      Там динамический сайт, так что ответы от fastcgi кешировать нечестно.
                      • НЛО прилетело и опубликовало эту надпись здесь
                          +1
                          Цель этого бенча — выяснить какая из систем работает лучше без кеширования.
                          С кешированием понятно, что будет еще лучше.
                      +4
                      Требую теста Apache prefork (по 1-2 процесса на кол-во физических ядер)+mod_php+nginx в режиме прокси. :-)
                        +1
                        Т.е. на этом сервере prefork должен создавать 4 процесса максимум.
                        Именно такой конфиг я использую у себя.
                          0
                          Они создаст 4 процесса, просто когда их backlog будет забит — напишет что надо повышать MaxClients ;)
                            +1
                            Это просто информация, работать будет все отлично, запросы будут собираться в nginx, а обрабатываться в apache по-очереди.
                              0
                              Ну данная связка уже 100 раз обсуждалась, последний Дмитрий Котеров большой коммент поданному поводу давал.

                              Численная разница будет максимум в некотором количестве памяти в пользу версии без апача (причины понятны), и то ее можно свести к минимуму убрав лишние модули.

                              Остальное — удобство конфигурирования, тут каждому свое.

                              Сам часто использую оба варианта, с апачем в середине обычно применяю когда есть правила mod_rewrite и их хочет менять разработчик.
                                0
                                Т.е. производительность Apache2+nginx не особо отличается от просто nginx?
                                А можно ссылки на обсуждения?
                                0
                                Все лишние модули были убраны с apache, иначе бы он не весил так мало.
                                  0
                                  Я лично не совсем понял почему «используете вариант с апачем, когда есть правила mod_rewrite». Что вам мешает эти правила прописать для Nginx, а не использовать ради них Апач?
                                    0
                                    Мне ничего не мешает :)
                                    Тут ключевой момент «хочет менять разработчик»…
                                    Если есть такое требование, то проще поставить апач за nginx и пусть он меняет в .htaccess сам.

                                      0
                                      с точки зрения хтаксесса, конечно, вопросов нет :)
                                        0
                                        Надо реквестировать модуль htaccess для nginx :)
                                        Хотя-бы для подмножества опций… типа access и rewrite для начала.
                            +1
                            Было бы интересно посмотреть независимое сравнение их с YAWS.
                            –1
                            А прогнать тот же тест на Apache+php-fpm не собираетесь для чистоты эксперимента, чтобы ясно увидеть (или не увидеть :) ), что именно nginx быстрее/надежнее Apache, а не php-fpm быстрее/надежнее mod_php?
                              –2
                              Тогда уже Apache надо ставить как worker + mod_fastcgi для «общения» с php-fpm.
                              Но все равно на больших нагрузках worker часто уходит в сегфолт.
                              +3
                              Вопрос был — даёт ли php-fpm существенный прирост производительности по сравнению с стандартными решениями. В данном тесте этот вопрос не изучался, изучалось влияние nginx на отдачу. То есть тест к спору отношения не имеет.
                              Теперь про сам тест. В общем я не понял что с чем сравнивалось. Работал ли апач с nginx как фронтенд. С какой машины делались запросы. Откуда такая куча failed запросов. Я бы такой тест не принял за обоснование чего бы то ни было — ни за, ни против.
                                0
                                nginx отдавал не статику, а проксировал именно к php-fpm. Сам по себе php-fpm никому ничего не дает, дает грамотная связка его с nginx :)
                                0
                                Хм… Если я правильно понимаю, основное преимущество nginx в том, что он не ест много памяти и процессора на каждый запрос. И его, в большинстве случаев, используют для раздачи статики — картинок, статичных хтмл, стилей, JS и т.д. «Тяжелые» же запросы (обработка php+mysql) отдают апачу.

                                Т.е. главная цель использования nginx+apache в том, чтобы сервер мог обслуживать большее количество запросов при тех же ресурсах. Ускорение обработки запросов является приятным побочным эффектом.
                                  0
                                  Мы, к примеру, отдаем и большие файлики nginx'ом, через X-Accel-Redirect (который выдает php скрипт на апаче, проверяющий доступы и т.п. и выдающий на nginx реальное физическое место файла на стораджах)

                                  P.S> в Opera 10.10 каменты перестали писаться
                                    0
                                    Вы это делаете, чтобы апач быстро отдал данные nginx и не висел без дела в памяти пока клиент получает данные по медленному каналу?
                                      0
                                      В общем да, только немного хитрее (в отличие от «стандартного» метода проксирующе-кеширующего nginx)

                                      Пользователь просит файл вида somehost.com/store/username/filename.ext
                                      Nginx спрашивает у скрипта на апаче этот файлик.
                                      Апач данные не отдает, являясь бекендом для nginx, выдает хидеры:
                                      X-Accel-Redirect с реальным именем файла на дисковой полке (а там система путей-подпапок с разбивкой по символам id файла), откуда файл отдаст сам nginx как статику.
                                      Либо если файл данному пользователю не доступен — скрипт на апаче выдаст нужный отбив 400-404-503, на который nginx ответит уже сам через перехват ошибок.

                                      В итоге апач со скриптом отвечает только хидерами достаточно быстро.
                                        0
                                        Т.е. файловая операция запись + файловая операция чтение быстрее передачи через tcp на одной машине? Хотя важно, чтобы только запись была быстрее этой передачи… Это так? Апач пишет на диск быстрее передачи через tcp на локалхост?
                                          0
                                          В нашем случае никуда ничего не пишется.
                                          Файлы лежат на дисковой полке, которая доступна машине с nginx (для nginx это локальные файлы)
                                          Для пользователя удобные ссылки на файлы, конечно же не совпадающие с физическим путем к файлам.
                                          У nginx просят файл, nginx лезет на апач бекенд по tcp на другую машину и спрашивает у его скрипта что-то типа: пользоватеь такой-то просит файл такой-то. Скрипт проверяет доступ пользователя к файлу (его устанавливает владелец файлика, права хранятся в базе), вычисляет физический путь к файлу в ФС полки. И отдает эту информацию на nginx. А уже тот отдает файл с себя, что он умеет делать быстро и не напряжно по ресурсам. Если бы отдавали апачем — на каждую отдачу висело бы по апачу с mod_php и тонной обвеса долго и печально.
                                            0
                                            Теперь понятно. Действительно, нестандартная и интересная схема. Обычно редиректы используют для таких случаев — проще, но плюс один запрос к nginx.
                                              +1
                                              Она стандартна. Описана в доке касающейся X-Accel-Redirect, ну и по идее это один из немногих способов вынести логику на основной бекенд с Apache+mod_php с готовым «движком» не написав эту логику отдельно под тот же PHP-FPM.
                                                0
                                                Ничего нестандартного, такая же возможность есть в Apache (mod_sendfile) и в Лайти.
                                      0
                                      Основное приемущество что сайт обрабатывают 4 процесса php + nginx. А вот Apache начинает форкать на каждый запрос по процессу и иногда не успевает отфоркать достаточно процессов. Отсюда и ошибки.
                                        0
                                        Я с большими нагрузками дела не имел… Действительно бывают ситуации, когда апач не успевает создавать процессы и сервер гибнет, даже имея достаточные ресурсы для их обработки именно из-за слишком большого времени создания процесса? Я до сих пор считал, что основная проблема в этом случае — проблема с памятью, которую апач всю занимает своими процессами… (БД и медленные каналы не рассматриваем сейчас).
                                          0
                                          Проблема как видно по бенчу в том, что он не успевал отфоркивать достаточное число процессов, что впрочем лечиться за счет памяти — при запуске дать сразу 1k процессов на старт.
                                            0
                                            >не успевал отфоркивать достаточное число процессов
                                            лечиться тридингом
                                              0
                                              Я даю при старте 7-10к процессов, памяти мне не жалко, я за нее денег заплатил, пусть работает.
                                            +1
                                            он начинает форкать на запрос по процессу, т.к. настроен неправильно, вот и все
                                              –2
                                              This Multi-Processing Module (MPM) implements a non-threaded, pre-forking web server that handles requests in a manner similar to Apache 1.3.

                                              Так что он будет полюбому форкать на запрос если кончились процессы и беклоги забиты.
                                                +2
                                                Объясните, пожалуйста, одну вещь. Есть у нас тут 2 алгоритма обработки запросов — «на каждый запрос создаем процесс» и «на каждый запрос создаем тред». И в apache, и в ngnix можно оба реализовать, используя разные модули и настройки.

                                                Почему Вы тогда на ngnix настроили работу по одному алгоритму, на apache — по другому, потом измеряете скорость и делаете вывод, что ngnix быстрее, чем апач? Это же ненаучное исследование, оно ничего не показывает, и, более того, отдаляет людей от понимания сути.

                                                Можно точно так же было настроить ngnix, чтоб он плодил новый процесс на запрос, и апач, чтоб он создавал тред, были бы обратные результаты.
                                          0
                                          Я бы лучше сравнил apache и lighttpd, по-моему они прямые конкуренты.
                                            0
                                            Я думаю что lighttpd является скорее прямым конкурентом Nginx а не Апача
                                              0
                                              Я и от такого сравнения не откажусь.
                                            +7
                                            Ну пипец.
                                            Apache
                                            Отключен Keepalive, а MaxClients и ServerLimit установлены в 10240
                                            1) Зачем отключен Keepalive?
                                            2) Очень умное решение — поставить 10 тыш клиентов. Естественно апачь при таком раскладе наплодит 700 процессов, которые естественно сожрут всю память, система естественно войдет в глубокую жопу-своп, и естественно не сможет нормально работать. Это не тест, какой сервер быстрее, это тест «Как завалить апачь».

                                            The MaxClients directive sets the limit on the number of simultaneous requests that will be served. Any connection attempts over the MaxClients limit will normally be queued, up to a number based on the ListenBacklog directive. Once a child process is freed at the end of a different request, the connection will then be serviced.
                                              +5
                                              Согласен по пункту 2. Но при включенном KeepAlive апач сдохнет еще быстрее.
                                                0
                                                Да не вопрос, можно поставить и 100 процессов. Их беклог быстро будет забит, и тест покажет что апач наплодил еще больше ошибок
                                                И да — вся память не сжиралась, что было видно по графикам. Так где-то под гиг.
                                              0
                                              Раскладка по утилизации CPU тоже явно не в пользу Apache.

                                              А разве не наоборот? idle на правом участке больше
                                                +1
                                                А зачем мне дорогой процессор — чтоб idle делал?
                                                Всегда думал чтоб быстрее задачи работали…
                                                +2
                                                Считаю данный тест бессмысленным. Если хотели сделать интригу, то надо было сравнивать Nginx vs Apache MPM worker хотя бы.
                                                  +1
                                                  Когда там будет стабильно работать mod_php, тогда и проверим.
                                                    0
                                                    А mod_php не стабильно работает с worker'ом? Предрассудки, или просто не так готовите.
                                                      +1
                                                      Нестабильно с mod_php mpm worker может работать (работал) из-за ошибок в mod_php, библиотеках и интерпретаторе php, которые делают код не thread-safe.

                                                      Если ошибки есть, то они точно так же будут влиять на любую другую конфигурацию, в которой php будет запускаться через треды, в.т.ч. на ту, что в статье. MPM worker стабилен ровно настолько же, насколько стабилен любой другой способ запуска php через треды.
                                                        0
                                                        А что мешало запустить PHP через FastCGI?
                                                      –7
                                                      Спасибо, за ваш труд, пишите еще, у вас хорошо получается ;)
                                                        0
                                                        На моё сайте буквально несколько дней назад удалил почти такой-же комментарий с замаскированной ссылкой на порно сайт.
                                                          0
                                                          Вы тут ссылку видите? Если да — купите очки, если нет — зачем писать?
                                                          PS: а хоть одно объяснение будет за что минусы то? ппц, вот люди пошли… школота одна.
                                                        +1
                                                        ИМХО, сравнение было бы гораздо интереснее, если бы в бенчмарке апача перед ним стоял NGINX как реверс-прокси. А так результаты вполне предсказуемы, конечно :D
                                                          +1
                                                          а почему использовали tcp-sockets, а не unix-sockets?
                                                            0
                                                            Спасибо за тест, жаль в нём не участвовал lighttpd.
                                                              0
                                                              Если гонять тест на производительность, то nginx с php-fpm следует равнять с Apache2 mpm-worker, например.
                                                              BTW на графике cpu кто-кого обогнал?
                                                                0
                                                                а и как при 4 Gb мозгов график до 20 GB получился? — Апач полез в своп и Вы там замеряли производительность? :)
                                                                0
                                                                еще написали как правильно кэширование в nginx настроить. а то у меня получилось, что сайт тупо весь закешировался, проц в IDLE на 99%, а залогиниться не могу. приэтом контент таки обновляется.
                                                                  –1
                                                                  Апач, поставленный через app-get неработоспособен вообще. На динамических сайтах апачега с пхп нужно собирать статичным бинарником и затачивать под каждый конкретный проект.
                                                                    0
                                                                    почему неработоспособен?
                                                                      0
                                                                      Ну хотя бы потому, что динамическое подсасывание модулей очень сильно его тормозит. А дефолтно он именно так и устанавливается. Апачег нужно тюнить и тюнить вдумчиво под конкретный проект, тогда он уделывает и нжинкса и лайтхттпд с боооольшим отрывом. Это опыт поддержки проектов с миллионами хостов в сутки.
                                                                        +1
                                                                        апач в принципе при отдаче не может уделать nginx. Никак и ни при каких настройках. Разве что сравнивать nginx как запускатель скриптов и апач как запускатель скриптов, без учёта медленных клиентов.
                                                                          +1
                                                                          Вы просто не видели, какие результаты дает apache+php=single-binary.
                                                                            0
                                                                            да хоть убейтесь — клиент, читающий ответ Вашего скрипта в течении минуты, всю эту минуту будет отжирать кучу памяти по сравнению с nginx, и в результате тормозить систему, которая имет хорошие шансы залезть в своп. Может быть, один запрос и быстрее отдаст апач без nginx, но это нереальный случай, реальный — много параллельных запросов.
                                                                          0
                                                                          какие именно проекты? ссылки и описание архитектуры?
                                                                            –1
                                                                            тут не принято давать ссылки на сайты про любовь =) Просто поверь =)
                                                                      0
                                                                      А почему php цепляется через TCP, а не по файловому сокету?
                                                                        0
                                                                        Бенчмарками не покормите?
                                                                        С налёту нашел тока про рельсы: macournoyer.wordpress.com/2008/01/26/get-intimate-with-your-load-balancer-tonight/
                                                                          0
                                                                          Неа, но по опыту быстрее.
                                                                            0
                                                                            с ходу — пакет в юних-сокете не пойдет гулять по файрволу, еще (точно не скажу) подозреваю, что оно гораздо легче тцп-стека
                                                                          0
                                                                          Как показывают опыты на Celeron 500, Nginx совсем не быстрее Jetty (без шуток).
                                                                            0
                                                                            требую теста apache-worker! )
                                                                              0
                                                                              Чтобы он слил? Вот здесь отлично документированный тест www.pentarh.com/wp/2008/07/11/test-results-apache-vs-php-fcgi/
                                                                              Правда там отдельно подбирали оптимальное число процессов для каждой схемы.
                                                                              Вкратце: все варианты практически не отличаются, но немного вырывается вперед apache1+mod_php.
                                                                              0
                                                                              Андрей, а ты здесь что с чем тестировал и какова цель эксперимента? Я пока что не вижу ничего кроме сравнения поведения газеты в дистиллированной воде и соляной кислоте. После озвучивания цели, очень хотелось бы узнать о методике выбора параметров тестируемых компонентов. Вот прямо картинкой и кружочком те места которые нас интересуют.
                                                                                0
                                                                                Появилась необходимость поработать над проектом в связке «Nginx + Php-fpm», но до сих пор была установлена связка «Nginx + Apache».
                                                                                Вопрос: могут ли сосуществовать и та и другая связка вместе?
                                                                                Например какие-то server прокидывают на Апач, а какие-то на Php-fpm?
                                                                                Мне интуитивно кажется что такое возможно. Но, так и не смог сейчас толком этого добиться.
                                                                                Почему-то всё равно схватывает и бросает на Апач, при том что fastcgi_pass php5-fpm-sock;
                                                                                Где php5-fpm-sock — это upstream на сокет. (https://coderwall.com/p/hmsr5a)
                                                                                Также использовал вот это (http://help.ubuntu.ru/wiki/nginx-phpfpm) для настроек.
                                                                                  0
                                                                                  В общем-то, сам разобрался ;)
                                                                                  Всё дело в правильных настройках!

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

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