Все началось с этой темы на форуме, когда многие на полном серьезе стали рассуждать, мол, nginx совсем не быстрее Apache, и даже перевод документации с официального сайта был неубедителен. Как известно, нет ничего более приятного, чем провести тестирование и показать график для привлечения внимания. Вот например график по обще нагрузке на сервер, попробуйте угадать где тут этап тестирования Nginx, а где — Apache.
Ну а перед тем как узнать правильный ответ — немного про сервер и механизм тестирования.
Дабы исключить всякие подозрения на «подкручивание» своих VDS, тест проводился на стороннем сервере, любезно предоставленным мне для теста одним из участников форума вот в такой кнофигурации:
AMD Athlon X2 5600+ 4 GB DDR2 2×400 GB HDD с Linux Debian в минимальной установке. Весь софт устанавливался стандартным образом — через apt-get. И PHP и Apache ставились в минимальном режиме.
Для объекта тестирования я поставил очень легкий блог Moscquito, который работает без MySQL, написав туда пару постов и камменты.
Прежде всего хочу сказать что перед запуском бенчмарка Nginx и Apache я перезагружал сервер. Сетевая подсистема была немного подкручена для более быстрой работы:
И повышались лимиты для корректной работы тестируемых и самих бенчмарков:
Для обоих веб-серверов был установлен таймаут в 300 секунд (стандартный для Apache, в Nginx он меньше).
Процессы были привязаны к TCP сокету, создано два пула по 4 процесса в каждом в статичном режиме.
Два воркера по 10240 коннектов каждый, php подключен как апстрим:
Отключен Keepalive, а MaxClients и ServerLimit установлены в 10240
Я постарался создать ситуацию сайта под DDOS атакой, когда 20k ботов долбят в главную страницу, а 5000 легальных пользователей ходят по сайту.
Импровизированную DDOS-атаку легко можно при помощи ab. А вот для пользователей пришлось сгенерировать карту сайта и натравить на нее siege.
Тестирование занимало час и запись о доступности сайта логгировалась с помощью ab. Вот какие две команды я паралельно запусал в screen'е:
Естественно, что для бенчмарка с апачем лог писался в apache.log
Как видно — число процессов изменялось только во время работы Apache, ну так недаром его MPM назвали Prefork. Nginx и PHP-FPM статичны, в чем их большой плюс.
К сожалению график памяти получился не очень красивым, но если посмотреть внимательно — памяти Apache потребляет больше.
Графики переключений между процессами и их форк очень интересно коррелируют между собой.
Раскладка по утилизации CPU тоже явно не в пользу Apache.
Расшифровка — за час работы связка Nginx+PHP-FPM успела пройти 38 итераций и завалить одну из них — 10629 ошибочных запросов. Это было связано с недоступностью апстрима — siege постарался, запустив большинство запросов на главную страницу.
А вот с Apache все плохо — даже если вычеркнуть 2 «удачных» попадания siege, то остаются еще ошибки + за отведенное время было выполнено меньше запросов.
Таким образом, по результатам тестирования связка Nginx+PHP-FPM побеждает Apache со счетом 38:23
Ну а перед тем как узнать правильный ответ — немного про сервер и механизм тестирования.
Дабы исключить всякие подозрения на «подкручивание» своих 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
Перейдем к графикам
Как видно — число процессов изменялось только во время работы Apache, ну так недаром его MPM назвали Prefork. Nginx и PHP-FPM статичны, в чем их большой плюс.
К сожалению график памяти получился не очень красивым, но если посмотреть внимательно — памяти Apache потребляет больше.
Графики переключений между процессами и их форк очень интересно коррелируют между собой.
Раскладка по утилизации 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