Оптимизация WEB-сервера. Дуэт Apache+Nginx делят нагрузку.

Кто помнит, недавно я писал статью о стресс-тесте для сайта. Результаты теста были не сказать, что прям совсем радостные. Но в целом терпимые. Читал-читал, копал-копал и решил наконец дело поправить.

Конечно, решено было в пользу mod_expires Апача (отдаёт неизменившуюся статику из кеша), а так же решено было вынести Апач в бэкэнд, а фронтэндом к нему сделать Nginx.

Как это работает? Что за странные слова FrontEnd, BackEnd…

Объясняю. На хостинге работает сразу два веб-сервера. Apache и Nginx. Апач я вынес на порт 8080, а Nginx на 80. То есть все запросы по умолчанию принимает Энжинкс. Далее, смотрим, что за запрос пришёл. Если это статический ресурс (jpg, gif, png, js, css) то отдаём клиенту сразу. Если динамическое содержимое (php), то запрос пересылаем на Apache, который выполняет код и возвращает результат клиенту.

Таким образом мы имеем как бы разделение труда. Apache для меня – мощный зверь, который можно гибко настраивать, обрабатывать php, .htaccess, использовать другие модули. Но заставлять его создавать новый поток, чтобы отдать клиенту gif-картинку – неразумно. Вместо этого есть проворный зверек Nginx, который работает в разы быстрее, но в нашей конфигурации он умеет только отдавать ресурсы (статику) и не может даже выполнить php, не говоря уж о преобразовании URL в Mod_rewrite и прочих плюшках.

Конечно, под Nginx можно настроить разные модули, расширяющие его функционал, но нам это не нужно! Требуется именно быстрый исполнительный веб-сервер, способный быстро отдать картинку-скрипт.

Итак, приступаем к установке. Она весьма тривиальна:

# apt-get install nginx

Конфиги лежат в /etc/nginx/

Итак, глушим сервер apache:

# /etc/init.d/apache2 stop

Немного изменим конфиг апача:

# mcedit /etc/apache2/ports.conf

Здесь поменяем порт:

...
NameVirtualHost *:8080
Listen 8080
...

Так же изменим все порты в виртуальных хостах:

<VirtualHost *:8080>
DocumentRoot "/var/www/litl-admin.ru"
...

Далее, создаем дополнительный файл конфигурации в nginx, который содержит параметры таймаутов, размеры буфера и замены заголовков запроса:

# mcedit /etc/nginx/proxy.conf

proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

Теперь меняем главный конфигурационный файл /etc/nginx/nginx.conf:

#пользователь, от имени которого работает веб-сервер
user www-data;
# количество работающих процессов (можно выставить равным количеству ядер сервера)
worker_processes 1;
error_log /var/log/nginx/error.log; #путь к файлу логу ошибок
pid /var/run/nginx.pid; #где хранится PID
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
access_log /var/log/nginx/access.log;
sendfile on;
keepalive_timeout 2;
tcp_nodelay on;
gzip on;
gzip_comp_level 3;
gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}

Теперь для каждого из наших виртуальных хостов сделаем аналогичный вихост в nginx:

upstream backend
{
#Адрес back-end'a
server 127.0.0.1:8080;
}
server
{
listen 80;
server_name www.litl-admin.ru litl-admin.ru;
access_log /var/log/www/litl-admin.ru/nginx_access.log;
error_log /var/log/www/litl-admin.ru/nginx_error.log;
# Перенаправление на back-end location /
{
proxy_pass http://127.0.0.1:8080;
include /etc/nginx/proxy.conf;
}
# Всю статику, скрипты, картинки - отдаём через nginx
location ~* \.(jpg|jpeg|gif|png|ico|css|bmp|swf|js)$
{
root /var/www/litl-admin.ru/; #Указываем путь к каталогу сайта
}
}

Внимание! Если вихостов несколько, то секцию upstream в остальных указывать не нужно. Она должна быть одна. Иначе nginx будет ругаться при старте.

А теперь делаем символическую ссылку:

# ln -s /etc/nginx/sites-available/litl-admin.ru /etc/nginx/sites-enabled/litl-admin.ru

И так для каждого виртуального хоста.

Ну теперь стартуем все сервера:

# /etc/init.d/apache2 start
# /etc/init.d/nginx start

Если выпали ошибки-опечатки – исправляем. Думаю, что всё должно запуститься нормально. Ну чтоже, пришла пора протестировать загрузку сервера. В начале статьи я приводил ссылку на материал, где я тестировал производительность веб-сервера. Вот скрин:

Примерно такая картина
Примерно такая картина

Как видите, при количестве одновременных подключений от 40 до 50, среднее время полной загрузки сайта составляет около 2 минут! Что явно великовато. А в середине теста даже Yandex метрика заругалась, что сайт недоступен.

Проверяем стресс-тест снова:

Стресс-тест
Стресс-тест

Как видите, среднее время на протяжении всего теста – порядка 3 секунды! Были кратковременные всплески до 12 секунд, связанные скорее всего с вмешательством в тест других пользователей, которые запрашивали крупные статьи с крупными изображениями. Но в целом нагрузка на сервер уменьшилась в десятки раз, что благоприятно сказалось на стабильности. Яндекс метрика не ругалась. Сайт отвечал более плавно.

Одним словом, я ни разу не пожалел о том, что поставил nginx на фронт-энд, убрав львиную долю нагрузки с apache.

Интересно? Поделись с другом
Litl-Admin.ru

Comments:

Leave a Reply