Веб-сервер на связке nginx+apache

Разворачиваем веб-сервер под операционной системой Linux, который будет использовать одновременно nginx и apache.

Пусть имеется аппаратная платформа, на которой уже установлен CentOS.

Настроим связку apache+nginx. На передовую (front-end) выставляем лёгкий и высокопроизводительный nginx, который будет обрабатывать запросы к статическому контенту (картинки, стили, js и т.п.). В тылу (back-end) нас будет страховать apache, задачей которого является предоставление динамического контента (в основном, PHP).

top-nginx-apache

Безусловно, возникает законный вопрос, нельзя ли обойтись без apache вообще? Действительно, ничего не мешает настроить совместную работу nginx+php+mysql (вызываем PHP в режиме FastCGI с помощью php-fpm). Производительность такой системы будет ещё выше. Но есть и серьезный недостаток: большинство стандартных движков сайтов ориентировано непосредственно на работу под apache (правила доступа к различным директориям сайта настраиваются в файле .htaccess); а ввиду того, что nginx не обрабатывает .htaccess, без доработок такие сайты под nginx работать не будут. Причем, если переработка одного сайта является вполне выполнимой технической задачей, то обслуживание нескольких сайтов (особенно чужих), становится настоящей проблемой.

Итак, жертвуем экстремальной производительностью, но сохраняем поддержку .htaccess.

Устанавливаем apache, mysql, php. Для этого нам пригодится yum и стандартные репозитории.

yum -y install httpd mysql mysql-server php php-mysql php-mbstring php-cli

Установка nginx чуть сложнее, придётся сходить на сайт разработчика и прочитать методику установки. К счастью, под распространенные дистрибутивы (CentOS и подобные), разработчик предоставляет готовые пакеты.

Настраиваем всю связку:

  • Конфигурация mysql
  • Конфигурация php
  • Конфигурация apache
  • Конфигурация nginx.

Теперь рассмотрим каждый шаг подробно.

Конфигурация mysql

Рассмотрена в соответствующей статье.

Конфигурация php

Практически не требуется, в деталях описана в отдельной статье. Главное не забыть про shorttag: short_open_tag = On.

Конфигурация apache

Так как на передовую мы выдвигаем nginx, значит именно он будет работать на стандартном порту 80, а обращение к apache будет проксироваться через любой другой порт. Я выбрал 8080.

Модифицируем файл глобальных настроек. Я привожу только самые важные параметры, которые надо проверить:

Timeout 60
KeepAlive Off
# MaxKeepAliveRequests 100
# KeepAliveTimeout 10

StartServers 2
MinSpareServers 2
MaxSpareServers 4
ServerLimit 6
MaxClients 10
MaxRequestsPerChild 800

# Слушаем нестандартный порт,
# так как у нас на передовой nginx
Listen 127.0.0.1:8080
# Пользователь и группа
User apache
Group apache
# Определяем порт
NameVirtualHost *:8080

Интересно, что KeepAlive следует отключать (спасибо за наводку внимательному читателю Mike). Производительность системы будет повышаться, если процесс httpd, отдав динамическое содержимое, будет тут же освобождаться.

Важно завести пользователя и группу, от которых будут работать в связке две службы: и nginx, и httpd. Естественно, это должен быть один и тот же пользователь как для httpd, так и для nginx во избежание конфликтов! Я для этих целей использую пользователя и группу apache; в результате httpd работает из-под "своего" имени, а nginx вынужден работать под чужим именем.

Следующим шагом будет настройка виртуальных серверов. Каждый виртуальный сервер будем настраивать, создавая для него отдельный конфигурационный файл в /etc/httpd/conf.d/, причем необходимо следить, чтобы расширением являлось именно .conf. Предположим, создаётся виртуальный сервер для сайта drach.pro, тогда потребуется файл /etc/httpd/conf.d/drach.pro.conf со следующим содержимым:

# Слушаем выбранный порт:
<VirtualHost *:8080> ServerName drach.pro
ServerAlias www.drach.pro
ServerAdmin Этот адрес электронной почты защищен от спам-ботов. У вас должен быть включен JavaScript для просмотра.
DocumentRoot /var/www/html/drach.pro
CustomLog /var/log/httpd/drach.pro_access.log combined
ErrorLog /var/log/httpd/drach.pro_error.log

<Directory "/home/drach.pro/www">
AllowOverride All
Options +Includes
</Directory>
</VirtualHost>


Таким образом необходимо описать все виртуальные сервера. Кроме того, надо не забыть про файлик vhost.conf, в который надо поместить конфигурацию сайта по умолчанию.

Теперь десерт! Не достаточно настроить apache на обычную работу, необходимо корректно обрабатывать REMOTE_ADDR заголовка. Для этих целей устанавливаем и настраиваем RPAF (mod_rpaf соответствует первой версии apache, а mod_rpaf2 - второй).

Без RPAF будем иметь REMOTE_ADDR не пользовательский, а IP-адрес сервера с передовой (это nginx). RPAF будет обрабатывать заголовок X-Forwarded-For, который получен от nginx и генерировать корректный REMOTE_ADDR.

Таким образом заголовок REMOTE_ADDR снова имеет пользовательский IP! Например, для моих целей это крайне важно, так как приходится наблюдать за пользователями и вести подробные логи для отчётов.

Устанавливаем модуль RPAF, для чего его придётся найти в интернете отдельным пакетом под наш дистрибутив. Есть альтернативный путь: подключить хранилище Atomic repo и использовать yum. Затем настраиваем RPAF, создавая и редактируя /etc/httpd/conf.d/mod_rpaf.conf:

LoadModule rpaf_module modules/mod_rpaf-2.0.so
RPAFenable On
# Enable reverse proxy add forward RPAFproxy_ips
YOUR_PROXY_SERVER_IP_LIST_OR_ONE_IP
# which ips are forwarding requests to us
RPAFsethostname Off
# let rpaf update vhost settings
# allows to have the same hostnames as in the "real"
# configuration for the forwarding Apache
RPAFproxy_ips 127.0.0.1
RPAFheader X-Real-IP

После конфигурации необходимо перезапустить Apache.

Конфигурация nginx

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

user apache;
worker_processes auto; разрешаем серверу выбирать количество процессов!
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}


http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

# Журналирование будет индивидуальное для всех сайтов:
# access_log /var/log/nginx/access.log main;

sendfile on;
client_max_body_size 24M;
#tcp_nopush on;
keepalive_timeout 65;

gzip on;
# Минимальная длина ответа, при которой модуль будет жать, в байтах
gzip_min_length 1100;
# Разрешить сжатие для всех проксированных запросов
gzip_proxied any;
# Запрещает сжатие ответа методом gzip для IE6
gzip_disable "msie6";
# Уровень gzip-компрессии
gzip_comp_level 8;

# 1) MIME-типы которые необходимо жать
#gzip_types text/plain text/html text/xml application/xml application/x-javascript text/javascript text/css text/json;
# 2) Если у вас появляются предупреждения, типа "duplicate MIME type text/html", то стоит исключить text/html
gzip_types text/plain text/xml application/xml application/x-javascript text/javascript text/css text/json;

# Хватаемся за соломинку:
#gzip_types text/html text/xml text/css application/x-javascript text/javascript;

include /etc/nginx/conf.d/*.conf;
}

Теперь конфигурируем виртуальные хосты! Причем, поступаем профессионально: конфигурационные файлы складываем в /etc/nginx/conf.d: например, для сайта drach.pro заводим отдельный файл /etc/nginx/conf.d/drach.pro.conf:

# A virtual host drach.pro

server {

# listen drach.pro:80;
listen 80;
server_name drach.pro;

# Ведём журнал доступа:
access_log /var/log/nginx/drach.pro_access.log;

# Разделяем статику и динамку, статику храним в кэше 10 дней:
location ~* \.(jpg|jpeg|gif|png|ico|css|bmp|swf|js|doc|docx|pdf|xls|xlsx|rar|zip|tbz|7z|exe)$ {
root /var/www/html/drach.pro/;
expires 10d;
}
# htaccess и htpasswd не отдаем:
location ~ /\.ht {
deny all;
}
# Мы хотим видеть статистику при обращении к папке /stat
location = /stat {
stub_status on;
access_log off;
# allow xx.xx.xx.xx;
# deny all;
}
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_redirect off;
log_not_found off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

Конец. Достаточно перезапустить все службы и убедиться, что веб-сервер работает!

service httpd restart && service nginx restart

Отслеживаем доступ к серверу в реальном времени:

tail -f /var/log/nginx/drach.pro_access.log

или

tail -f /etc/httpd/logs/drach.pro_access.log

Ежели в консоли браузера появляется ERR_INCOMPLETE_CHUNKED_ENCODING (обычно это бывает, если файлы css и js генерируются "на лету"), необходимо проверить права и владельца директории /var/cache/nginx/proxy_temp. Также есть смысл убрать эти два расширения из разрешённых статических типов файлов для nginx.

 

Ежели в журнале ошибок появляется upstream response is buffered to a temporary file, следует в файл глобальной конфигурации nginx добавить proxy_max_temp_file_size 0; в секцию http.

13 комментарии

Авторизуйтесь, чтобы получить возможность оставлять комментарии

Другие материалы в этой категории:

Go to top