RTFM.WIKI

Ordnung muß sein. Ordnung über alles (18+)

Инструменты пользователя

Инструменты сайта


linux:nginx:apache_vs_nginx

Apache vs Nginx: Расставим точки над ё.

Источник: http://slonik-v-domene.livejournal.com/141951.html

Наступивший январь порадовал нас очередным сравнением теплого с мягким Apache vs Nginx как платфом для работы с PHP.

Перед тем как комментировать заметку рекомендую все же дочитать ее до конца и осилить разбор полетов. Если желания читать нет, краткая суть: автор сравнения провел тесты неверно, без понимания сути происходящего. К реальности все его выводы не имеют никакого отношения вовсе.

Теперь объяснение, почему так.

Я потрудился перепроверить полученные результаты на собственном стенде. Выбранная система - 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

<IfModule mpm_prefork_module>
    StartServers          5
    MinSpareServers       5
    MaxSpareServers      10
    MaxClients          250
    MaxRequestsPerChild   0
</IfModule>

/etc/apache2/sites-available/example.com

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com

    DocumentRoot /opt/www/example.com/htdocs

    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
    CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>

Если вы не видите в списке значение какого-либо параметра, значит оно оставлено без изменений из конфигурации "по умолчанию".

Сам файл:
/opt/www/example.com/htdocs/index.php

<?php for($i = 0; $i < 1000; ++$i) { echo "Hello, World! $i "; }

Тесты проведены утилитой 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]

Мы видим следующие вещи:

  1. при возрастании конкурентности уменьшаются как разница в результатах, так и скорость ответа
  2. nginx в любой конфигурации при небольшой и средней конкурентности медленнее apache/mod_php
  3. nginx+fpm через unix socket быстрее nginx+fpm через tcp socket
  4. 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 по сути - двунаправленный пайп, фактически, данные копирутся из одного буфера в другой без задействования сетевой подсистемы.

Почему при увеличении конкуренции разница уменьшается?

Потому, что становится важным тот факт что система тратит ресурсы на шедулинг процессов (и 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%, а прежде всего на технологическом удобстве (удобстве разработки, деплоймента, необходимости дополнительной обработки запроса и т.п.)

Обсуждение

Ваш комментарий. Вики-синтаксис разрешён:
 
linux/nginx/apache_vs_nginx.txt · Последнее изменение: 2018/03/12 15:50 — 127.0.0.1