Pull to refresh

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

Configuring Linux *
Все началось с этой темы на форуме, когда многие на полном серьезе стали рассуждать, мол, 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
Tags:
Hubs:
Total votes 85: ↑74 and ↓11 +63
Views 27K
Comments 95
Comments Comments 95