Установка Nginx как фронтенда к Apache на сервер c WHM/Cpanel
Меня окончательно утомили тормоза апача на моем ВДС (700 метров памяти, центос-5, whm/cpanel, апач 2.2, куплен в ТекТонике, рекомендую). Причина банальна - выжирание памяти апачем при довольно смешной нагрузке в 2-2.5 тысячи пользователей в день. Тюнинг maxclients помог, но не сильно (зарежешь число клиентов чтобы стало больше свободной памяти - начинаются еще более страшные тормоза).
Поэтому было принято дальше кота за яйца не тянуть и перейти на схему с фронтендом на Nginx и бэкэндом на апаче. Схема давно стала фактически индустриальным стандартом для тяжело нагруженных серверов, для тех, кто в танке вот тут человеческим языком объясняется почему такая схема эффективна.
Основная проблема заключалась в том, что прикрутить надо было не к голому серверу, а установленной панельке WHM/Cpanel, что поначалу казалось непросто. За основу был взят вот этот мануал, но в нем многое было не описано, подразумевалось, что ты, типа, старый линуксоид, и тебе и так все понятно. Я же опишу для идиотов, типа себя, чтобы потом не забыть.
Начать надо с установки mod_rpaf на апач. Он нужен для того, чтобы апач получал правильные адреса посетителей от nginxa.
Логинимя под рутом, далее
cd /root/tmpmkdir mod_rpaf
cd mod_rpaf/
wget http://stderr.net/apache/rpaf/download/mod_rpaf-0.6.tar.gz
tar xzf mod_rpaf-0.6.tar.gz
cd mod_rpaf-0.6
/usr/local/apache/bin/apxs -i -c -n mod_rpaf-2.0.so mod_rpaf-2.0.c
Последняя строчка собственно устанавливает модуль.
Теперь надо прописать настройки модуля. Идем в WHM, Main >> Service Configuration >> Apache Setup > Include Editor > Pre Main Include и вставляем там приведенный код:
RPAFenable On # Enable reverse proxy add forward RPAFproxy_ips 127.0.0.1 LIST_OF_YOUR_IPS # which ips are forwarding requests to us RPAFsethostname On # let rpaf update vhost settings # allows to have the same hostnames as in the “real” # configuration for the forwarding Apache RPAFheader X-Real-IP # Allows you to change which header mod_rpaf looks # for when trying to find the ip the that is forwarding # our requests List_of_your_IPs меняем на список купленных к серверу адресов, через пробел. Жмем сохранить, перезапустить апач. Ахтунг! при докупке свежих IP их всех нужно будет потом руками прописывать в этом месте
Теперь нам надо перетащить апач на какой нибудь другой порт, например 81, потому что на стандартный 80 порт мы будем сажать nginx. Для этого в WHM идем в Tweak settings и правим порт на котором висит апач - 0.0.0.0:80 на 0.0.0.0:81. Жмем “apply” - ответа мы уже не дождемся, порт поменян. При необходимости можно зайти по http://whm.че-то-там.com:81 Обратите внимание, что https мы не переносим. Если есть желание, можно попробовать перенести и его за nginx, но особо смысла не вижу.
Возвращаемся в консоль - нам надо поправить настройки prefork’a в конфиге апачи. Для начала убедитесь, что у вас используется именно prefork, используя: httpd -V | grep MPM
Поравьте соответствующий раздел конфига
vi /usr/local/apache/conf/httpd.conf,
поправьте на что-то вроде этого: <IfModule prefork.c>
StartServers 5
MinSpareServers 5
MaxSpareServers 5
MaxClients 100
MaxRequestsPerChild 100
</IfModule> Если у Вас worker, то раздел, естественно, другой.
Теперь нужно конфиг продистилировать скриптами WHM, чтобы он нормально прососался:
/usr/local/cpanel/bin/apache_conf_distiller –update –main /scripts/rebuildhttpdconf
поправтье номер порта 80 на 81 в настройках сервиса мониторинга vi /etc/chkserv.d/httpd и перезапустите его: /etc/init.d/chksrvd restart или /etc/init.d/chkservd restart сервис может называться по разному, в крайнем случае ребут вас спасет. На этом с апачем мы закончили, ставим nginx (по мотивам отсюда): Нам понадобится компилятор, ставим его если еще нет: yum -y install gcc pcre-devel zlib-devel Скачиваем и распаковываем nginx: mkdir /root/tmp/nginx
cd /root/tmp/nginx
wget http://sysoev.ru/nginx/nginx-0.6.35.tar.gz
tar xzf nginx-*.tar.gz
cd nginx-*/
Устанавливаем: ./configure
make
make install
ln -s /usr/local/nginx/conf /etc/nginx Прописываем ротацию логов: vi /etc/logrotate.d/nginx
туда: /usr/local/nginx/logs/*log {
daily
rotate 7
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
/bin/kill -USR1 `cat /usr/local/nginx/logs/nginx.pid` 2> /dev/null || true
endscript
}
Делаем инит-скрипт: vi /etc/init.d/nginx
туда: #!/bin/sh
#
# Init file for nginx server daemon
#
# chkconfig: - 85 15
# description: nginx server daemon
#
bin=’/usr/local/nginx/sbin/nginx’
pid_file=’/usr/local/nginx/logs/nginx.pid’
case “$1″ in
start)
echo -n “Starting nginx: ”
$bin && echo OK || echo FAILED
;;
stop)
echo -n “Stopping nginx: ”
kill `cat $pid_file` && echo OK || echo FAILED
;;
configtest)
$bin -t
;;
reload)
echo -n “Reloading nginx: ”
kill -HUP `cat $pid_file` && echo OK || echo FAILED
;;
restart)
$0 stop
sleep 1
$0 start
;;
*)
echo “Usage: $0 {start|stop|restart|reload|configtest}”
exit 1
;;
esac
и прописываем автозагрузку (runlevel 3)
ln -s ../init.d/nginx /etc/rc3.d/S99nginx Теперь нам надо прицепить скрипт, который генерит конфиги nginxa на основании насроек whm. Мы запихаем его в /scripts/postwwwacct, чтобы он обновлял конфиги после каждого добавления аккаунта: vi /scripts/postwwwacct туда: #!/bin/sh
cat > “/usr/local/nginx/conf/nginx.conf” <<EOF
user nobody;
worker_processes 2;
error_log logs/error.log info;
worker_rlimit_nofile 8192;
events {
worker_connections 512; # increase for more busy servers
use rtsig; # you should use epoll here for Linux kernels 2.6.x
}
http {
server_names_hash_max_size 2048;
include mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 10;
gzip on;
gzip_min_length 1100;
gzip_buffers 4 32k;
gzip_types text/plain text/html application/x-javascript text/xml text/css;
ignore_invalid_headers on;
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;
connection_pool_size 256;
client_header_buffer_size 4k;
large_client_header_buffers 4 32k;
request_pool_size 4k;
output_buffers 4 32k;
postpone_output 1460;
include “/usr/local/nginx/conf/vhost.conf”;
}
EOF
/bin/cp /dev/null /usr/local/nginx/conf/vhost.conf
cd /var/cpanel/users
for USER in *; do
for DOMAIN in `cat $USER | grep ^DNS | cut -d= -f2`; do
IP=`cat $USER|grep ^IP|cut -d= -f2`;
ROOT=`grep ^$USER: /etc/passwd|cut -d: -f6`;
echo “Converting $DOMAIN for $USER”;
cat >> “/usr/local/nginx/conf/vhost.conf” <<EOF
server {
access_log off;
error_log logs/vhost-error_log warn;
listen 80;
server_name $DOMAIN www.$DOMAIN;
# uncomment location below to make nginx serve static files instead of Apache
# !WARNING!
# it will make the bandwidth accounting incorrect as these files won’t be logged!
#location ~* .(gif|jpg|jpeg|png|wmv|avi|mpg|mpeg|mp4|htm|html|js|css)$ {
# root $ROOT/public_html;
#}
location / {
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
# you can increase proxy_buffers here to suppress “an upstream response
# is buffered to a temporary file” warning
proxy_buffers 16 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_connect_timeout 30s;
proxy_redirect http://www.$DOMAIN:81 http://www.$DOMAIN;
proxy_redirect http://$DOMAIN:81 http://$DOMAIN;
proxy_pass http://$IP:81/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
EOF
done
done
service nginx restart
Теперь проверим, чего он нагенерил: /usr/local/nginx/sbin/nginx -t Стартуем nginx: /usr/local/nginx/sbin/nginx И - вуаля! На всякий случай стоит проверить поведение сервера после ребута. Результаты можете оценить сами.
Статья супер! Впервые вижу так детально описанное решение по cpanel, которое немедленно можно использовать в работе. Относительно скрипта генерации виртуальных хостов к nginx - есть замечание.
Если в субдоменах есть * (напр. *.domen.name) - тогда при выборке этого домена из настроек юзера и генерации для него конфига получаем такую запись: http://www.*.domen.name - на что nginx честно ругается:
[emerg]: invalid server name or wildcard “www.*.domen.name” on 0.0.0.0:80
Надо, наверное, проверять * и не генерировать для него вообще с префиксом www ни server_name, ни proxy_redirect.
И еще один момент - дополнительные домены - если раскомментировать отдачу статики - для них она отдаваться не будет вообще (404), т.к. root - не $ROOT/public_html, а $ROOT/public_html/some_add_domain_dir
Art, да, скрипт мной был честно утащен отсюда - http://figvam.blogspot.com/2008/05/using-nginx-to-accelerate-apache-on.html, чел его писал для сервачка под собственные нужды (как в общем то и я использую). Для multi-user, хостинга и т.п. стоит наверно поправить ;)
Nginx можно настроить более универсально используя $host в proxy_pass и не забыв указать опцию resolver. Подробно написал у себя в блоге.
Для мультихостинга мне пришлось поломать голову и переписать скрипт с нуля.
В итоге он учитывает все Addon, sub, parked domains и субдомены вида *.domain.com
Вроде все учел.
Правило proxy_backend введено для случаев rewrite_rule на html, например и прочие файлы, которых в действительности не существует, а php их генерирует.
Подробнее тут:
http://lanselot.me/2011/02/nginx-apache-and-cpanel/