Настройка Nginx как Frontend к Web-серверу Apache

В данной статье будет рассмотрена настройка Nginx с целью повышения эффективности работы вашего Web-сервера при значительных нагрузках. Повышение эффективности достигается использованием легкого Web-сервера nginx, который принимает и обрабатывает все запросы от пользователей, оправляя Apache только необходимый минимум. Прямого доступа к Web-серверу Apache пользователь не получает.

Приступим к настройке. В моем случае настройка производится на дистрибутиве Linux Debian 6.0.

Устанавливаем программное обеспечение:

# apt-get install apache2 nginx

После этого меняем параметры соединений, поскольку нам необходимо запустить Apache на другом порту. В нашем случае — это 8080, но вы можете использовать любой на ваш вкус. Для изменения порта правим строчки в конфигурационном файле /etc/apache2/ports.conf:

NameVirtualHost *:8080
Listen 8080

Так же необходимо внести соответствующие изменения в файлы виртуальных хостов. Для примера создадим виртуальный хост sample.ru.

В целях повышения производительности можно отключить Keep Alive соединения. Для этого поправим директиву в файле /etc/apache2/apache2.conf

KeepAlive off

Важно: Если у вас дистрибутив Linux не Debian или Ubuntu, то расположение конфигурационных файлов и их имена могут отличаться. Например, в большинстве случаев все настройки хранятся в общем конфигурационном файле /etc/apache2/httpd.conf. Так же в некоторых дистрибутивах Linux и Unix сам Apache может располагаться в иных директориях. Возможные варианты:

  • /etc/apache2
  • /etc/httpd
  • /usr/local/etc/apache2
  • /usr/local/etc/httpd
  • /usr/local/etc/www
  • /usr/local/apache2
  • /usr/local/httpd
  • /usr/local/www

Это те варианты, которые мне встречались в практике на различных платформах. Далее, все настройки будут приводиться в привязке к дистрибутивам Linux Debian и Linux Ubuntu, а вы самостоятельно делайте поправку на свой случай.

Создание виртуального хоста в apache

Создаем новый файл /etc/apache2/sites-available/sample.ru. В файл помещаем следующий текст:

<VirtualHost *:8080>
    ServerAdmin webmaster@sample.ru
    ServerName www.sample.ru
    ServerAlias sample.ru

    DocumentRoot "/var/www/sample.ru/"

    ErrorLog ${APACHE_LOG_DIR}/sample.ru-error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn

    CustomLog ${APACHE_LOG_DIR}/sample.ru-access.log combined

</VirtualHost>

Важно не забыть поставить порт 8080 в директиве VirtualHost!

Активизируем наш виртуальный хост и перезапускаем апач:

# a2ensite sample.ru
# /etc/init.d/apache2 restart

Теперь наш виртуальный хост доступен по адресу:

http://sample.ru:8080

Верный REMOTE_ADDR для Apache

В связке с Nginx Apache будет распознавать REMOTE_ADDR как адрес локального хоста 127.0.0.1, даже несмотря на то, что в настройках Nginx мы будем передавать явно REMOTE_ADDR. Для решения этой проблемы достаточно установить модуль Apache RPAF. В Debian он обычно включен в метапакет Apache, поэтому его достаточно просто активировать и перезапустить Apache:

# a2enmod rpaf
# /etc/init.d/apache2 restart

Настройка Nginx

В нашем случае настройка Nginx будет ограничена минимальным объемом работы, необходимым только для эффективной работы Nginx связки с Apache.

Для начала, объясню общую идею всей нашей работы. Nginx принимает запросы от пользователей на 80 порту, далее принимает решение перенаправить запрос к Apache или обработать его самостоятельно. К Apache уходят запросы связанные с отображением динамического содержимого, например: обработка php-скриптов. Статическое содержиное Nginx отдает самостоятельно без участия Apache. К статическому у нас отностяся файлы картинок, текстовые файлы, таблицы стилей, JavaScript файлы, иконки, XML-файлы и пр. Будьте осторожны с обработкой запросов к файлам html. Дело в том, что на сайтах с включенным ЧПУ запрос к html файлу через модуль Apache mod_rewrite может приводить к запуску скрипта для возврата корректного содержимого. Во избежании ошибок запросы к html файлам тоже должен обрабатывать Apache.

Ранее мы отключили у Apache поддержку Keep Alive. В связке с Nginx такая мера дает ощутимый припрост производительности. Apache обработав запрос и вернув содержимое Nginx, отключается и переходит к обработке других запросов, а процесс Nginx уже самостоятельно занимается отправкой результата пользователю. Ресурсов процесс Nginx практически не потребляет, поскольку фактически работает только со статикой. Apache же может жрать просто огромное количество ресурсов.

Приведу пример одного из моих проектов, который имеет более 10 тыс. посетителей в сутки. Запросов, соответственно к сайту просто коллосальное количество. Сайт работает на достаточно ресурсоемком движке Bitrix. Одно обращение к сайту отхватывает от 300Мб до 2,5Гб оперативной памяти. Если проект запустить без Front-end, то сайт при текущей загруженности будет тормозить по-черному, если вообще сможет обрабатывать запросы. Что мы получаем в итоге работы связки. Сервер достаточно мощный, поэтому даже ресурсоемкие запросы обрабатывает мгновенно. Apache обработав запрос, сразу отдает содержимое Nginx и освобождается для обработки следующего запроса. Nginx, обрабатывая запрос к конкретной странице, уже использует всего 0,5-2Мб оперативной памяти. Ощутимая разница! За счет этого нагруженный проект вполне себе нормально живет. Конечно, в приведенном примере есть еще особенности настройки MySQL сервера, но тема настройки MySQL выходит за рамки данной статьи. Обязательно сделаю статью и на тему базовой настройки MySQL для работы с Bitrix на больших проектах.

Кстати, если говорить о Bitrix, то тема настройки Front-end на серверах с сайтами под Bitrix крайне актуальна, особенно, если Интернет-магазин реализован на этой CMS. При всей громоздкости Bitrix, эта CMS уверено набирает популярность, поскольку имеет массу дополнений для работы с 1С:Предприятием. Административная часть вполне дружелюбна для пользователя, особенно в сравнении с CMS распространяемыми по лицензии GPL. 1С программисты могут создавать выгрузки товаров из 1С:Предприятия в любых разрезах и с любыми параметрами руководствуясь просто стандартами обмена данными 1С.

Итак, перейдем непосредственно к настройке.

Основной конфигурационный файл Nginx /etc/nginx/nginx.conf

Собственно, тут делаем минимальные изменения. Если каких-то директив у вас не хватает, просто добавьте их в соответствующие разделы файла. Чуть ниже я разъясню назначение некоторых директив и их значений.

#Пользователь под которым работает процесс
user www-data;

# Количество рабочих процессов, зависит от ваших задач и ресурсов оборудования
worker_processes  5;

# Общий лог для ошибок
error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;

events {
    # Максимальное количество рабочих соединений
    worker_connections  1024;
    # multi_accept on;

    # Метод обработки соединений, разъяснение - ниже
    use epoll;
}

http {
    include       /etc/nginx/mime.types;

    access_log    /var/log/nginx/access.log;

    # Задаёт таймаут при чтении заголовка запроса клиента
    client_header_timeout    3m;

    # Задаёт таймаут при чтении тела запроса клиента
    client_body_timeout        3m;

    # Задаёт таймаут при передаче ответа клиенту
    send_timeout        3m;

    # Задаёт таймаут, в течение которого keep-alive соединение
    # с клиентом не будет закрыто со стороны сервера
    keepalive_timeout        3m;

    # Разрешает или запрещает использовать sendfile()
    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    #keepalive_timeout  65;
    tcp_nodelay        on;

    gzip  on;
    gzip_disable "MSIE [1-6]\.(?!.*SV1)";

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Методы обработки соединений директива use раздела events

С выбором метода обработки соединений нужно быть внимательным. Разные методы поддерживаются разными операционными системами.  nginx поддерживает различные методы обработки соединений. Если на платформе доступно сразу несколько методов, nginx обычно сам выбирает наиболее эффективный метод. Однако, при необходимости можно явно выбрать метод обработки соединений с помощью директивы use. Если не уверены, лучше директиву вообще отключить.

Поддерживаются следующие методы обработки соединений:

  • select — стандартный метод. Модуль для поддержки этого метода собирается автоматически, если на платформе не обнаружено более эффективного метода. Можно принудительно разрешить или запретить сборку этого модуля с помощью параметров —with-select_module и —without-select_module.
  • poll — стандартный метод. Модуль для поддержки этого метода собирается автоматически, если на платформе не обнаружено более эффективного метода. Можно принудительно разрешить или запретить сборку этого модуля с помощью параметров —with-poll_module и —without-poll_module.
  • kqueue — эффективный метод, используемый во FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 и Mac OS X. Во многих русскоязычных руководствах по настройке Nginx в качестве Front-end для Apache встречается указание именно этого метода, поскольку большинство статей тупо переводные и изначально писались админами FreeBSD или OpenBSD.
  • epoll — эффективный метод, используемый в Linux 2.6+. В некоторых старых дистрибутивах, например SuSE 8.2, есть патчи для поддержки epoll ядром 2.4.
  • rtsig — real time signals, эффективный метод, используемый в Linux 2.2.19+. По умолчанию в общесистемной очереди событий может одновременно находиться не более 1024 сигналов. На нагруженных серверах может потребоваться увеличить размер очереди с помощью параметра ядра /proc/sys/kernel/rtsig-max. Однако, начиная с Linux 2.6.6-mm2, этого параметра уже нет и для каждого процесса существует отдельная очередь сигналов, размер которой ограничивается с помощью RLIMIT_SIGPENDING и может быть изменён с помощью worker_rlimit_sigpending.
  • /dev/poll — эффективный метод, используемый в Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+ и Tru64 UNIX 5.1A+. При переполнении очереди nginx сбрасывает её и начинает обрабатывать соединения с помощью метода poll до тех пор, пока ситуация не нормализуется.
  • eventport — event ports, эффективный метод, используемый в Solaris 10.

Настройка виртуального хоста для Nginx

У самого Nginx, как и у Apache есть свои виртуальные хосты. Поэтому для нашего сайта нам нужно указать виртуальный хост sample.ru. Создаем файл /etc/nginx/sites-available/sample.ru. В файл помещаем содержимое:

server {

    listen   80; ## listen for ipv4
    #listen   [::]:80 default ipv6only=on; ## listen for ipv6

    server_name  sample.ru www.sample.ru;

    access_log  /var/log/nginx/sample.ru-access.log;

    # Максимальный размер тела запроса клиента
    client_max_body_size 10M;

    location / {
        proxy_pass http://127.0.0.1:8080/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_connect_timeout    120;
        proxy_send_timeout    120;
        proxy_read_timeout    180;
    }

    # Статику Nginx отдает самостоятельно без участия Apache
    location ~* \.(ico|docx|doc|xls|xlsx|rar|zip|jpg|jpeg|txt|xml|pdf|gif|png|css|js)$ {
        root   /var/www/sample.ru/;
    }

}

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

# ln -s ../sites-available/sample.ru ../sites-enabled/sample.ru
# /etc/init.d/nginx restart

Итог настройки Nginx в качестве Front-end для Apache

Если все сделали без ошибок, связка должна заработать. На нагруженных проектах эффект будет виден сразу.