====== Apache vs Nginx: Расставим точки над ё. ====== {{tag>apache fpm httpd nginx php}} Источник: http://slonik-v-domene.livejournal.com/141951.html Наступивший январь порадовал нас [[http://www.eschrade.com/page/why-is-fastcgi-w-nginx-so-much-faster-than-apache-w-mod_php/|очередным сравнением]] теплого с мягким Apache vs Nginx как платфом для работы с PHP. Перед тем как комментировать заметку рекомендую все же дочитать ее до конца и осилить [[http://slonik-v-domene.livejournal.com/142305.html|разбор полетов]]. Если желания читать нет, краткая суть: автор сравнения провел тесты неверно, без понимания сути происходящего. К реальности все его выводы не имеют никакого отношения вовсе. Теперь объяснение, почему так. Я потрудился перепроверить полученные результаты на собственном стенде. Выбранная система - Ubuntu 12.04.3 LTS, ядро - Linux 3.8.0-29-generic x86_64. Установка проведена методом "Yes -> Yes -> Ok -> Restart". Из стандартных репозиториев были доустановлены пакеты: apache2-mpm-prefork 2.2.22-1ubuntu1.4 libapache2-mod-php5 5.3.10-1ubuntu3.9 nginx-full 1.1.19-1ubuntu0.5 php5-fpm 5.3.10-1ubuntu3.9 Хотя в этом и не было никакого смысла (один-единственный отдаваемый файл и так был бы закеширован) по настоятельной просьбе был создан Ram-disk размером 64М: mkfs -q /dev/ram1 65536 mount /dev/ram1 /opt/www/example.com Конфигурация сервисов:\\ **/etc/nginx/sites-available/example.com** server { listen 8080; root /opt/www/example.com/htdocs; index index.html; server_name example.com; location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; } # location / # { # proxy_pass http://127.0.0.1:80/; # } } Для тестирования nginx+Apache/mod_php использовалась закомментированная часть файла конфигурации. **/etc/php5/fpm/pool.d/www.conf** pm.max_children = 250 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 10 pm.max_requests = 0 **/etc/apache2/apache2.conf** StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxClients 250 MaxRequestsPerChild 0 **/etc/apache2/sites-available/example.com** ServerName example.com ServerAlias www.example.com DocumentRoot /opt/www/example.com/htdocs Options FollowSymLinks AllowOverride None ErrorLog ${APACHE_LOG_DIR}/example.com-error.log CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined Если вы не видите в списке значение какого-либо параметра, значит оно оставлено без изменений из конфигурации "по умолчанию". Сам файл:\\ **/opt/www/example.com/htdocs/index.php** Тесты проведены утилитой ab с различной конкурентностью. Проводилось пять замеров, два самых медленных результата отбрасывались, данные по остальным трем замерам осреднялись. Стоит отметить, что при использовании php-fpm количество переданных данных было меньше из-за разницы в количестве передаваемых данных по протоколу FastCGI. Так как разница в объеме трафика составила около 1%, этим расхождением можно смело пренебречь. Чтобы исключить сайд-эффекты от недостатка памяти и вычислительной мощности, тестирование велось на сервере с заведомо достаточным количеством оперативной памяти и CPU. **Apache:** Total transferred: 180820000 bytes HTML transferred: 178900000 bytes **Nginx:** Total transferred: 180490000 bytes HTML transferred: 178900000 bytes **Concurrency Level: 10** Apache: 1407.41 [#/sec] Nginx/fpm-unix: 1108.12 [#/sec] Nginx/fpm: 1102.07 [#/sec] Nginx/apache: 1040.58 [#/sec] **Concurrency Level: 50** Apache: 1273.71 [#/sec] Nginx/fpm-unix: 1106.68 [#/sec] Nginx/fpm: 1083.58 [#/sec] Nginx/apache: 1009.34 [#/sec] **Concurrency Level: 100** Apache: 1288.83 [#/sec] Nginx/fpm-unix: 1095.26 [#/sec] Nginx/fpm: 1085.20 [#/sec] Nginx/apache: 989.68 [#/sec] **Concurrency Level: 200** Apache: 1054.37 [#/sec] Nginx/fpm-unix: 1045.21 [#/sec] Nginx/fpm: 993.68 [#/sec] Nginx/apache: 978.78 [#/sec] Мы видим следующие вещи: - при возрастании конкурентности уменьшаются как разница в результатах, так и скорость ответа - nginx в любой конфигурации при небольшой и средней конкурентности медленнее apache/mod_php - nginx+fpm через unix socket быстрее nginx+fpm через tcp socket - nginx+apache/mod_php работает сопоставимо с nginx+fpm На этом статью можно было бы закончить и дать всем желающим возможность сделать далеко идущие очевидные и при этом неправильные выводы. Тем не менее, я прокомментирую полученные результаты. **Почему так и с какой стати nginx работает медленее?** При использовании nginx+fpm мы имеем два разных сервера: nginx на порту 8080 и fpm на порту 9000. Нетрудно догадаться, что nginx работает как прокси для сервера fpm, сначала принимая запрос извне и затем отправляя его к серверу fpm по протоколу FastCGI. Если же используется apache/mod_php, запросы обрабатываются непосредственно на сервере без проксирования куда-либо. Очевидно, что при всех тех же самых условиях двузвенная система (ab <-> apache) будет работать быстрее чем трехзвенная (ab <-> nginx <-> fpm), отсюда и полученные результаты. Если же мы используем unix socket, накладные расходы на транспортировку данных между nginx и fpm уменьшаются, причем особенно хорошо это заметно при большой конкурентности. Это и понятно - unix socket по сути - двунаправленный пайп, [[http://lists.freebsd.org/pipermail/freebsd-performance/2005-February/001143.html|фактически, данные копирутся из одного буфера в другой без задействования сетевой подсистемы]]. **Почему при увеличении конкуренции разница уменьшается?** Потому, что становится важным тот факт что система тратит ресурсы на шедулинг процессов (и fpm и apache создают необходимое количество процессов для обработки запросов), а также то, что возрастает вычислительная нагрузка на процессор и систему виртуальной памяти - на это тоже тратятся ресурсы. **Стоит ли отказаться от Nginx-fpm в пользу Apache/mod_php?** Короткий ответ: Да. Нет. В зависимости от задач. Длинный ответ: даже в самом простом случае кроме запуска PHP требуется отдавать и статику (html, css, js, картинки и т.п). Nginx с этой задачей справляется куда как лучше чем Apache. Кроме того, nginx в состоянии одновременно обслуживать очень большое количество подключений, что также недоступно в случае использования Apache. Поэтому роль nginx как правило заключается балансировке нагрузки, отдаче статики, проксированию запросов к PHP на внутренние сервера, а самое главное - к работе с медленными клиентами. В этом случае логично поднять php-fpm и обрабатывать запросы к php через него. Если же требуется сложная работа с реврайтами, дополнительными модулями apache, фильтрами содержимого и подобными вещами и это требуется делать вместе с модулем php, имеет смысл поставить Apache/mod_php. При этом вы должны очень хорошо понимать, что вы делаете и какой результат хотите получить. Выставлять ничем не прикрытый Apache в мир, прочтя англоязычную статью и захотев получить прирост 1-10% по скорости ответа - очень, очень плохая идея. Не делайте так. **Менее очевидный вывод** Apache, как парзер протокола HTTP и запускальщик модулей, написан хорошо. В нем с его архитектурой "один-процесс-на-одного-клиента" практически нечего улучшать, поэтому все его альтернативы (например, php-fpm) работают с сопоставимой скоростью. В ряде задач требуется именно такой подход (например, для обработки изображений "на лету"), поэтому Apache с соответствующим модулем - хороший и правильный выбор. **Любителям "оптимизаций"** Чудес не бывает. Все сервера с архитектурой вида "1 запрос - 1 процесс" ведут себя практически одинаково: у них сопоставимые скорости работы и примерно похожее поведение под возрастающей нагрузкой. Выбор конечного решения должен основываться не на мифическом приросте производительности в 6-10%, а прежде всего на технологическом удобстве (удобстве разработки, деплоймента, необходимости дополнительной обработки запроса и т.п.)