В одном из наших проектов вызрела надобность горизонтального расширения количества веб-серверов. Первое что пришло на ум - это установка балансировщика нагрузки. Но вот "на беду" параллельно с этим встала задача побыстрее отдавать статический контент. Для решения этой разумеется выбран nginx, хотя до сих пор не парились и работали только с apache. Итак, какие заморочки придумали.
Наши сайты (а у нас их около 70, мы не хостинг, это всё наши) решили поделить на три кучи:
1. То, что будет балансироваться;
2. То, что не будет балансироваться и обрабатываться только apache;
3. То, что не будет балансироваться и будет обрабатываться nginx.
Решили начать с того, чтобы поднять nginx. Здесь все оказалось просто, документации куча, но есть нюанс... Логика работы такая - всё обрабатывается nginx, а php передаётся в apache. Однако, существует такая штука, как динамически создаваемые файлы. Так вот, в этом случае nginx подумает, что обращение за файлом должен обрабатывать он, но файла нет и клиент увидит 404. Решение есть и не одно. Привожу пример конфига nginx:
Первый вариант:В секции http конфига nginx указываем
http {
...
#этим мы укажем, что у нас существует некий сервер (apache), который висит на 127.0.0.1
#сам nginx у нас висит на 127.0.0.1:8080 так как есть ещё балансер на внешнем интерфейсе
upstream nextserver {
server 127.0.0.1;
}
#эта секция нужна, чтобы в apache передать реальные адреса клиентов
set_real_ip_from 50.ххх.ххх.59; # внешний адрес балансера
real_ip_header X-Forwarded-For;
port_in_redirect off;
...
# остальные настройки, а также...
# Load config files from the /etc/nginx/conf.d directory
include /etc/nginx/conf.d/*.conf;
} # end of http
В каталоге /etc/nginx/conf.d мы держим настройки для каждого домена, который будет обслуживаться nginx. Каждый домен в своём файле. Пример:
server {server_name .domain.net;
access_log /home/www/domain.net/logs/access_log;
error_log /home/www/domain.net/logs/error_log;
location / {
root /home/www/domain.net/httpdocs;
#Проба на файл, если файла нет, оправляемся искать в локацию nextserver, то есть на apache
try_files $uri $uri/ @nextserver;
}
include /etc/nginx/conf.d/common-config;
}
А в файле /etc/nginx/conf.d/common-config хранится неизменяемая часть, одинаковая для всех доменов:
listen 127.0.0.1:8080;index index.html index.php;
#Локация nextserver используется для передачи данных в apache так же как передаются данные для обработки php
location @nextserver {
proxy_pass http://nextserver;
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;
}
location ~ \.(php|htm)$ {
proxy_pass http://127.0.0.1;
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;
}
Собственно всё. Есть второй вариант обработки не найденного файла. Для этого вносим некоторые изменения в файл /etc/nginx/conf.d/common-config, после чего он выглядит так:
listen 127.0.0.1:8080;index index.html index.php;
#как только получили код 404 отправляемся за ним на apache
error_page 404 = @notfound;
location @notfound {
proxy_pass http://127.0.0.1;
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;
}
location ~ \.(php|htm)$ {
proxy_pass http://127.0.0.1;
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;
}
А файл описания домена выглядит ещё проще
server {
server_name .domain.net;
access_log /home/www/domain.net/logs/access_log;
error_log /home/www/domain.net/logs/error_log;
location / {
root /home/www/domain.net/httpdocs;
}
include /etc/nginx/conf.d/common-config;
}
Теперь apache. Задача перенастройки apache свелась к тому, чтобы в конфигурациях виртуальных серверов заменить адрес на 127.0.0.1. Затем нужно получить от апача реальный адрес клиента. В nginx мы уже провели подготовку, но этого мало. Проблема решается установкой модуля mod_extract_forwarded, который берет данные из заголовка X-Forwarded-For и передает их в REMOTE_ADDR. Конфигурационный файл модуля примитивен:
LoadModule extract_forwarded_module modules/mod_extract_forwarded.soMEForder refuse,accept
MEFrefuse all
#Разрешает локальный адрес и адрес балансера
MEFaccept 127.0.0.1 50.ххх.ххх.59
MEFaddenv on
MEFdebug off
И наконец, самое вкусное: haproxy. Впечатления балансер оставляет самое положительное. Работает очень быстро, настройки простые и гибкие. Используем версию 1.5.1, так как там есть пара удобных функций.
global #общие настройкиlog 127.0.0.1 local2 #куда пишем логи
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 10000 #максимальное число коннектов к балансеру
user apache #по-умолчанию балансер работает от пользователя haproxy
group apache
daemon
defaults #настройки по-умолчанию
mode http
log global
option dontlognull
option httpclose
option httplog
option forwardfor #это нужно, чтобы заполнить X-Forwаrded-For и передать бекэнду
option redispatch
option httpchk HEAD / HTTP/1.0
cookie serv insert
timeout connect 5000 # default 5 second time out if a backend is not found
timeout client 10000 # 10 sec
timeout server 90000 # 10 sec
maxconn 10000
retries 3
frontend main 50.ххх.ххх.59:80 #вешаем балансер на внешний интерфейс
#читаем файлы с именами доменов и в зависимости от того какой домен в каком файле
#используем то или иное правило балансировки
acl host2apache hdr_beg(host) -i -f /etc/haproxy/unbalanced-apache
acl host2nginx hdr_beg(host) -i -f /etc/haproxy/unbalanced-nginx
acl url_static path_beg -i /mrtg /munin
use_backend nginx if url_static
use_backend nginx if host2nginx
use_backend apache if host2apache
default_backend balanced #по-умолчанию коннект пойдет на балансировку
#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
# небалансированный бекэнд для доменов из списка
#---------------------------------------------------------------------
backend apache
balance roundrobin
server static 127.0.0.1:80 check
backend nginx
balance roundrobin
server static 127.0.0.1:8080 check
#
#---------------------------------------------------------------------
# round robin balancing between the various backends
# серверы, на которые пойдет распределение нагрузки
#---------------------------------------------------------------------
backend balanced
balance roundrobin
server web1 50.ххх.ххх.214:80 check
server web2 50.ххх.ххх.210:80 check
server web3 50.ххх.ххх.211:80 check
Вот такое решение трёхслойного пирога с вишенкой. Извращение, конечно, но работает.
Комментариев нет:
Отправить комментарий