Установка и настройка Nginx как frontend для Apache

Ни для кого не секрет, что большинство сайтов интернета работают на серверах под управлением Linux. так же ни для кого не секрет, что львиная доля этих сайтов написана на PHP работающему в связке с БД MySQL. А еще, многие в курсе, что Apache обслуживающий ваш сайт может жрать кучу памяти, серверного времени и вообще тормозить из-за так называемых медленных клиентов — это когда клиент с плохим каналом отправляет запрос на ваш сайт о получении страницы и апач честно отдает её ему и ждет, пока клиент получит эту информацию и вернет ответ об этом. Это узкое место апача, так как при таком подходе остальные клиенты ожидают своей очереди из-за одного медленного клиента. В это же время перестает обслуживаться выполнение скриптов и т.д. В общем ситуация достаточно тривиальная и можно было бы не обращать на это внимания, при условии что у вас сайт не получает к примеру одновременно по 500 посетителей каждую минуту. Что же делать если это именно так?

Выхода из ситуации два — либо ставить вместо Apache+php связку nginx+php-fpm (что в некоторых случаях может заставить вас пересмотреть используемые инструменты в виде CMS и т.п.), либо ставить nginx в качестве frontend для apache. Второй способ может быть и не так сильно ускорит ваш веб-сервер, зато никаких дополнительных настроек для работоспособности веб-ПО на нем выполнять не придется, особенно это касается систем управления контентов зависимых именно от apache.

Итак. Установка nginx в качестве frontend производится в 2 этапа. Первый — установка и настройка nginx, второй — настройка apache на прием запросов от nginx.

Установка и настройка nginx.

Во первых — наглядная картинка схемы работы системы которую мы хотим получить:

Схема Nginx+Apache
Схема Nginx+Apache

 

 

 

 

 

 

 

 

 

 

 

Схема упрощенная, так что гусарам молчать :)

В целом логика понятна — нжикс принимает запросы, статику отдает сразу, а то обработку динамики отдается апачу, который передает результат работы нжиксу и тот далее отдает её уже клиенту. Смысл в том, что нжикс для отдачи статичного контента не ожидает завершения выполнения скриптов как апач, а делает это сразу, паралельно ожидая от апача результата его работы.

Выполним установку и настройку. Я покажу как это сделать на примере Debian. Вам возможно будет удобнее сделать на своём дистрибутиве. Принцип один и тот же.

Устанавливаем Nginx:

Остановите nginx сервер если он был запущен автоматически пакетным менеджером и создайте новый конфигурационный файл nginx.conf к директории по умолчанию /etc/nginx by default – с содержимым примерно такого вида:

Nginx должен запускаться под тем же пользователем что и Apache чтобы избежать ошибок прав доступа. Замените apache на имя пользователя под которым ваш Apache запускается – обычно по умолчанию в Debian и Ubuntu это пользователь www-data. Кроме того в этом конфигурационном файле есть некоторые настройки для улучшения производительности, такие как use epoll — метод событийной модели эффективно работающая на ядрах Linux 2.6+. Эта опция работает в тандеме со следующей, accept_mutex off, что еще немного повышает производительность. Включение sendfile позволяет nginx использовать поддерживаемый ядром sendfile для отправки файлов клиенту вне зависимости от их содержимого. Это поможет при работе с большими статическими файлами — такими как картинки, которые не требуют обработки большого количества  запросов/подтверждений. Включение gzip сжатия для статики может дать вам большое увеличение производительности. Линия начинающаяся с gzip включает сжатие для определенных веб-файлов,  таких как .css и .js файлы, поддерживаемых браузером. Вы можете более полно узнать обо всех доступных опциях в документации к nginx, на wiki проекта.

Создайте директорию /etc/nginx/virtual.d и файл DOMAIN.TLD.conf для каждого виртуального хоста настроенного в Apache, со следующим содержимым:

Замените DOMAIN.TLD на нужное доменное имя, а /srv/DOMAIN.TLD/html на публично-доступную директорию домена. Так же удалите или добавьте расширения файлов определяющих что у вас является статичным контентом; эти файлы будут обслуживать nginx.

Настройка Apache

Теперь у нас nginx работает в качестве frontend веб-сервера, и ожидает запросов на порту 80 – значит вам нужно сконфигурировать Apache для прослушивания другого порта (8080 например) и только запросов посылаемых от имени localhost. В Debian и Ubuntu откройте файл /etc/apache2/ports.conf и измените строку

Listen 80

на

Listen 127.0.0.1:8080.

На CentOS такие же настройки выполняются в файле /etc/httpd/conf/httpd.conf file. В зависимости от вашего дистрибутива, если вы используете name-based виртуальные хосты, вы должны изменить строку

NameVirtualHost *:80

на

NameVirtualHost *:8080.

Если вы настраивали поддержку Keep-Alive в Apache вы должны отключить её, так как она уже поддерживается вашим nginx. Измените

KeepAlive On

на

KeepAlive Off

в файле /etc/httpd/conf/httpd.conf (CentOS) или/etc/apache2/apache2.conf (Debian/Ubuntu).

Вы так же можете отключить модуль mod_deflate так как nginx уже выполняет gzip сжатие. Хорошей идеей будет отключить вообще все неиспользуемые модули Apache для высвобождения системных ресурсов.

Оба сервера теперь должны запускаться без проблем. Если один из них не стартует, проверьте конфигурации:

и

или

в Debian/Ubuntu.

В этом месте наших настроек, если вы посмотрите в файл access.log у Apache вы увидите что все входящие запросы идут только с адреса 127.0.0.1. Для исправления ситуации вам требуется установить mod_rpaf. Пользователи Debian и Ubuntu могут установить пакет libapache2-mod-rpaf  и перезапустить Apache. На CentOS придется установить модуль из исходников. Дополнительно вам потребуются для этого пакеты httpd-devel и gcc. После установки создайте файл /etc/httpd/conf.d/mod_rpaf.conf со следующим содержимым:

Пользователям Debian так же следует проверить файл /etc/apache2/mods-enabled/rpaf.conf на предмет того, что строка с параметром RPAFproxy_ips выглядит так же как в примере для CentOS выше. После перезапуска Apache в файле access.log все IP адреса будут выглядеть нормально, но информации в логе поубавиться. Это нормально, так как статичный контент у нас теперь обрабатывается через nginx.

На этом всё. Надеюсь вам будет полезно :)

Автор: Mirivlad

Скромный труженик консоли и окошек.

Комментарии:

Установка и настройка Nginx как frontend для Apache: 44 комментария

  1. >>nginx+php-fpm (что в некоторых случаях может заставить вас пересмотреть используемые инструменты в виде CMS и т.п.)

    Это ты о чем?

    >>ставить nginx в качестве frontend для apache. Второй способ может быть и не так сильно ускорит ваш веб-сервер

    не сильно, да… порой, в десятки раз :)

    1.  >>Это ты о чем?
      О том что бывает что какая-нибудь cms дюбелями прибита к апачу и без него не заработает. не встречал таких? велкам в риал ворлд :)
      >>не сильно, да… порой, в десятки раз :)
      не будем о грустном :)

      1. php абсолютно без разницы как его исполняют с помощью fpm или с помощью mod_php, это скорее называется «не умею настраивать, не осилил — решил, что проблема в CMS».

        1.  окей. ты не поимеешь проблем если у тебя cms завязана на юзание mod_rewrite да? :)

          1. А какие могут быть проблемы? nginx даже гибче в настройке.

            Там, где апачу нужен rewrite, в nginx-е можно обойтись даже без rewrite-ов, простыми location-ами и правильной установкой параметров.

            1.  про это я в курсе. а если cms генерит htaccess и сама дописывает туда реврайт-правила и т.п.? как тогда быть? :)

              1. Да, бывают такие через жопу сделанные cms-ки. Но, как правило, они генерят простейшие вещи, поэтому ставите хук и преобразуете это в соответствующие правила nginx, делаете ему reload-файла конфигурации.

                И все работает просто, быстро и автоматически без вашего вмешательства.

            1. суть в том была чтто при отказе от апача реврайты придется дописывать в конфиге нжикса. может быть просто не особо понятно выразил мысль :)

      2.  >>не встречал таких?

        за всю свою практику ниразу. fpm — это лишь патч, который увеличивает производительность пыха в работе с ним как cgi, не более. Так что примеры в студию

        1.  не помню название. каюсь. но сталкивался с cms которая генерит htaccess добавляя туда правила реврайтов. идиотизм, согласен, однако человек пользовался, и даже был доволен.

  2. >>worker_connections 1024;

    быстро упрешься в лимит и начнешь радоваться 502

    1.  хорошо — сколько предлагаешь ставить их для двуядерной (заметь — два ядра — то бишь либо один двуядерный проц, либо два одноядерных)

      1.  cpu тут роли не играет. Можешь раз 5 увеличивать и не переживать.

        1.  хм. ну не бесконечно же их увеличивать? во что упрется нжикс если увеличивать число воркеров? в память?

          1. worker_connections — ни коем образом не влияет на число воркеров.

            1. Под воркерами обычно подразумеваются его родительские процессы, которые умеют порождать форки для отработки worker_connections (коннектов)

  3. >>location ~* ^.+.(htm|htmlя понимаю, что ты оптимист. но вот этого делать не стоит, потому что90% сайтов работать у тебя не станет :) Догадаешься почему?

    1. >>я понимаю, что ты оптимист, но вот этого делать не стоит, потому что 90% сайтов работать у тебя не станет :)
      Догадаешься почему?
      Это ты про ~* намекаешь? :)

      1.  нет, это я намекаю на чудо-кодеров, которые любят в *.html заталкивать php-код

        1.  я пока с таким не сталкивался. ну и упаси бог — как говорится :)

    2. >>Что-то не понял, и что ты получишь? Все то же — локальный ip’шник в
      логах. Перечислить необходимо через пробел все ip’шники твоего сервера
      Почему? Указывается айпишник на котором работает фронтенд. а внешний или внутренний — какая разница апачу то?

      1.  на локалхосте, разумеется, никакой. Но на локалхосте и рпаф не нужен. И указывается не ip’шник, а ip’шники, которые слушает фронтенд.

    3. >>>>На CentOS придется установить модуль из исходников
      >>Или поставить пакет mod_rpaf.x86_64, к примеру :)
      Ну утверждать не буду что это именно так. Вроде у федора-проекта был репозиторий с названием на Е начинающийся — вроде там тоже есть этот пакет :)  Не центовод — не в курсе :)

  4. ^.+.(htm|html|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|bz2|pdf|odt|txt|tar|bmp|rtf|js|swf|avi|mp4|mp3|ogg|flv)$это называется «не умею писать даже простейшие регулярные выражения».
     

    1. А в чем проблема?
      Как раз здесь проблем нет, тут просто перечисление форматов статики, не более

      1. «^.+» — типа гоняем процессор впустую?
        (..) — захватываем и не используем, расходуем память впустую?
        htm|html -> html?
        jpg|jpeg -> jpe?g
        tgz|gz -> t?gz
        mp4|mp3 -> mp[34]

        1. >>html?
          емнип ? в регэкспе это одиночный символ — у тебя получается же что это типа htmla htmls htmld и т.д. нет разве?
          зы. регекспы не особо люблю — потмоу в тонкости не вдавался в такие. Однако даже если у тебя правильно все — приведенный пример — более читабелен

          1. «емнип ? в регэкспе это одиночный символ — у тебя получается же что это типа htmla htmls htmld и т.д. нет разве?»

            Нет.
            man pcresyntax

            » приведенный пример — более читабелен »
            Для тех, кто не умеет писать regexp-ы — возможно. Т.е. для людей не связанных с ИТ и админством. Но им настройку серверов обычно не доверяют.

            …и менее производителен.

            1. >>…и менее производителен.
              Тестировал? графики/таблицы сравнений есть?

              1. «Тестировал?»
                Писал патчи для libpcre и знаю, как работает pcre-шный интерпретатор. Тут выигрыш конечно минимальный, но это не оправдывает вашей дремучести. Админ, не знающий назначение метасимвола «?» в регулярных выражениях, просто профнепригоден.

              2. А если вам хочется увидеть конкретных цифр, то ваша регулярка вдвое медленнее:

                 re> /^.+.(htm|html|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|bz2|pdf|odt|txt|tar|bmp|rtf|js|swf|avi|mp4|mp3|ogg|flv)$/
                data> path/to/ht/somefiljgq/css/media/mp/mp4.css
                Execute time 0.0020 milliseconds
                 0: path/to/ht/somefiljgq/css/media/mp/mp4.css
                 1: css
                data>
                  re> /.(?:html?|jpe?g|gif|png|ico|css|zip|t?gz|bz2|pdf|odt|txt|tar|bmp|rtf|js|swf|avi|mp[34]|ogg|flv)$/
                data> path/to/ht/somefiljgq/css/media/mp/mp4.css
                Execute time 0.0010 milliseconds
                 0: .css

            2.  ты пытаешься выжать производительность в том, в чем выжимать ее нет смысла. Какая тебе разница с одной миллиардной секунды? Именно такой прирост ты и пытаешься получить. Все это обсасывалось уже тыщу раз. И я сам лично тыщу раз проверял как на серверах с посещаемостью в 100к уников посуточно, так с 3мя миллионами в час. Есть и примеры, если так интересно

        2.  я тебе вот что скажу — укоротить всегда можно, само собой. Но это не тот случай, где реально что-то сможешь выжать. И еще:

          mp[34] будет работать медленнее mp4|mp3 — сюрприз!

          1. «mp[34] будет работать медленнее mp4|mp3 — сюрприз! »
            С чего бы это?

          2. вот и мне подумалось на основе опыта — что правило будет медленнее обычного перебора. хотя смотря что перебирать)))

            1. Сравните:

              $ pcretest -d
              PCRE version 8.21 2011-12-12

                re> /mp[34]/
              ——————————————————————
                0  40 Bra
                3     mp
                7     [34]
               40  40 Ket
               43     End
              ——————————————————————
              Capturing subpattern count = 0
              No options
              First char = ‘m’
              Need char = ‘p’

                re> /(?:mp3|mp4)/
              ——————————————————————
                0  24 Bra
                3   9 Bra
                6     mp3
               12   9 Alt
               15     mp4
               21  18 Ket
               24  24 Ket
               27     End
              ——————————————————————
              Capturing subpattern count = 0
              No options
              First char = ‘m’
              No need char

  5. >>error_log off;
    Restarting nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    [emerg]: open() «/usr/local/nginx/off» failed (2: No such file or directory)

    меняем на
    error_log /dev/null crit;
    ~# service nginx restart
    Restarting nginx: nginx. 

Комментарии запрещены.