Thu 18 May 2006
Использование Nginx Как Reverse-Proxy Сервера На Загруженных Сайтах
Posted by Scoundrel under Networks ·
Две недели назад мы запустили новую версию одного из наших оcновных веб-проектов и начали массивную рекламную поддержку этого сайта. В результате рекламы, исходящий трафик только с одного сервера достиг 200-250Mbit/s! В данной статье я опишу, как построить стабильный и эффективный веб-сайт с двухуровневой архитектурой обработки запросов (с двумя веб-серверами: frontend и backend) или как модифицировать ваш текущий сервер, чтобы получить дополнительные ресурсы для обработки большего количества запросов.
Для начала, опишу типичный процесс обслуживания запроса к веб-серверу и структуру самого сервера:
- Клиент инициирует запрос к серверу.
- Его браузер устанавливает соединение с сервером.
- Ваш сервер (например, Apache) создает новый поток/процесс для обработки запроса.
- Если клиент запросил динамический контент (например, отправил запрос к php-скрипту), веб-сервер создает отдельный CGI-процесс или запускает модуль обработки скриптов (например, mod_php) и ждет, пока запрос будет обработан. Как только он получает результирующую web-страницу, то она отправляется клиенту.
- Если же клиент запросил статический файл, то сервер просто отправляет этот файл клиенту.
- Браузер клиента получает ответ, закрывает соединение с сервером и отображает “ответ”.
Как видите, если к серверу приходит очень много запросов, он должен создавать много параллельных потоков/процессов и держать их в памяти, пока клиент не закроет соединение. Если соединение у клиента не быстрое, то серверные процессы будут висеть в памяти достаточно долго и используемые ими ресурсы будут увеличиваться очень быстро.
Как же решить данную проблему? Простым решением может быть бесконечное увеличение объемов оперативной памяти на сервере и покупка дополнительных или более мощных процессоров в ожидании момента, когда сервер умрет под нагрузкой… Но существует более эффективное решение! Вы можете просто поместить небольшую программку (nginx, например) перед Вашим большим веб-сервером и дать ей возможность обслуживать запросы к статическим файлам, а запросы к динамике проксировать к главному серверу. При таком решении Ваш большой сервер не будет создавать дополнительных процессов для обработки статических страниц и файлов и будет отдавать результаты обработки динамических запросов маленькому frontend-серверу очень быстро, что позволит ему освободить ресурсы для использования в обработке других запросов. Маленький frontend же может ждать сколь угодно долго, пока клиент заберет свой “ответ” и закроет соединение, а backend не будет тратить ресурсы для этого!
Вот примерная диаграма предложенной конфигурации веб-сервера:
В дополнение к описанному, Вы получите еще очень удобную возможность так называемых контролируемых закачек, которая будет описана ниже.
Если Ваш сервер содержит какие-то статические ресурсы, которые можно скачивать только определенной части аудитории сайта (контент-провайдеры могут предоставлять возможность скачивания mp3-файлов только пользователям с положительным балансом; некоторые сайты дают скачивать файлы только зарегистрированным пользователям и т.п.), в типичном случае вам необходимо создать некий скрипт для обработки запросов на скачивание и создать набор жутких ссылок вида http://some.service.com/down.php?file=xxx.mp3… В дополнение к этому Ваши пользователи не будут иметь возможность докачки (исключая те случаи, когда Ваш скрипт настолько сложен, что понимает заголовок Ranges в HTTP-запросах)…
В конфигурации с использованием nginx как frontend-сервера, Вы имеете возможность создать простое правило для переписывания ссылок в запросах так, чтобы все красивые ссылки типа http://your.cool-service.com/files/cool.mp3 автоматически направлялись на некоторый скрипт /down.php и, если он вернет заголовок X-Accel-Redirect, файл автоматически отдавался клиенту с поддержкой Ranges и всех остальных прелестей раздачи статического контента с frontend-сервера. Backend-сервер в это время сможет обрабатывать другие запросы. Ваши пользователи могут даже не знать о том, что их закачки контролируются Вами. Примерная диаграмма описанного алгоритма приведена ниже:
Позвольте обратить Ваше внимание на важный факт: Если Вам нужно только увеличение производительности работы сайта с помощью описанной здесь техники, и вы не хотите использовать систему контроля за скачиванием, то Вам не нужно ничено менять в скриптах на Вашем сервере! Они будут работать так же, как и раньше!
Итак, последнее, чем я могу помочь Вам в тяжелом труде оптимизации использования ресурсов Вашего сервера, - это пример конфигурации для nginx, которая может быть использована Вами в качестве базовой при конфигурации Вашего сервера:
listen 80;
server_name some-server.com www.server-name.com;
access_log logs/host.access.log main;
# Main location
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
# Static files location
location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {
root /spool/www/members_ng;
}
}
Полная версия конфигурационного файла лежит здесь.
Замечание: Если скрипты на Вашем backend-сервере используют IP-адреса клиентов в каких-то целях, то Вам необходимо установить на сервер модуль mod_rpaf module, чтобы он использовал передаваемый nginx заголовок X-Real-IP в качестве основного адреса пользователя.
Вот и все! Теперь Вы можете установить себе на сервер nginx, отконфигурировать его и получить возможность обслуживать большее количество клиентов при использовании меньшего количества ресурсов! Все будет работать абсолютно прозрачно для уже написанных скриптов и, если хотите, Вы сможете организивать контролируемое скачивание при помощи метода, который я опишу в одном из следующих постов.
Если у Вас есть какие-либо вопросы, задавайте их в комментариях не откладывая - я попробую ответить на них. Если эта статья понравилась Вам, можете обратить внимание на рекламные объявления на этой стратице или просто проголосуйте за нее на Digg.com.
- HAProxy - Надежный, высокопроизводительный балансировщик нагрузки для TCP/HTTP
- Обзор Типичных Конфигураций Для Nginx
- Использование X-Accel-Redirect с Nginx для реализации контролируемых скачиваний (с примерами для rails и php)
- MySQL Proxy Released
- Сбор Статиcтики О Работе Сервера nginx При Помощи rrdtool
June 7th, 2006 at 5:12 pm
cool i love alex
July 29th, 2006 at 5:15 pm
А как избавиться после ридеректа на apache от нолмера порта в урле? В моём случае http://greg.dobroe.net:8080/pma/
July 29th, 2006 at 7:08 pm
2greg: Использовать директиву proxy_redirect.
August 31st, 2006 at 2:11 am
Подскажите пожалуйста, как сделать так, чтобы из определённой папки nginx отдавал файлы “как есть” - картинки - картинками, скрипты - файлами (download), не переадресовывая запрос. Т.е. цель - запрет исполнения всего в папке, но возможность скачивания без ошибок. Переопределение типа на application/octet-stream для этой папки результата не даёт
August 31st, 2006 at 2:51 am
2Thegirl: И оно действительно отдает application/octet-stream? Проверьте через curl/GET/wget…
November 1st, 2006 at 5:44 am
[...] You would be able free some resources on server while nginx will handle all slow requests to dynamic content (details are here). [...]
November 8th, 2006 at 3:28 pm
Алексей, добрый день.
как с этим бороться?
Возникла ситуация:
есть один тяжёлый проект
бежит это на nginx
добавили несколько дополнительных серверов с FastCGI
происходит потеря сессий
Заранее благодарен за ответ.
November 8th, 2006 at 6:16 pm
Что вы имеете ввиду под “потеря сессий”? Если то, что пхп-шные сессии перестали работать, так это логично - они ведь в файлах во дефолту хранятся. Решений я знаю как минимум 2:
1) хранение сессий на nfs-share
2) хранение сессий в базе данных
December 20th, 2006 at 5:35 am
A quick config question…
I’m reverse proxying to an Apache server…when I run a script that takes a lil’ while to produce some input (e.g. an Amazon product fetching script) nginx will sometimes not present the output, even though the Apache script is still churning away in the background. What timeout setting do I need to adjust in this situation?
January 22nd, 2007 at 7:35 am
Очень познавательно, теперь я знаю, что такое nginx.
February 27th, 2007 at 7:27 am
Спасибо Алекс, очень полезная статья.
Расскажите плз чем вы такие красивые блок схемы строите?
March 3rd, 2007 at 11:10 am
Ребят, помогите, пожалуйста! никак не могу “подружить” nginx с апачем
у нас на сервере крутятся два сайта.
скажем, q5Video.ru и q5Magazine.ru
в конфиге nginx я прописываю код:
server {
listen 81.17х.х.хх:80;
server_name q5Magazine.ru http://www.q5Magazine.ru;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
# Static files location
location ~* ^.+.(midi|wav|flv|bmp|rtf|js)$ {
root /spool/www/members_ng;
}
и в кофиге апача прописываю
listen 127.0.0.1:8080
что здесь неправильно?
March 10th, 2007 at 12:14 pm
I wonder if it makes sense to use nginx as a server for static files _behind_ an existing Apache frontend. If have an Apache configuration with several virtual hosts and set it up to proxy requests for static files to nginx, but from what I read on the web everyone else does it the other way around.
Would my setup be less effective under heavy load conditions?
March 10th, 2007 at 6:07 pm
2rubyrobot: Your configuration would not help to handle higher loads… Idea of nginx-before-apache scheme is in following: nginx would handle lots of traffix and apache would not even know about this traffic.
March 13th, 2007 at 1:09 pm
scoundrel: I am not sure if that’s the right thing for me. More then 90% of requests are dynamic on my server. There’s only a few requests to large static files, about 200MB in size. If I put nginx in front, it produces a lot of unnecessary overhead, because 90% of requests go straight through the nginx proxy.
I am under the impression that a time consuming 200MB request proxied through Apache to nginx will not keep one of Apache’s large child processes busy that could be better used to process dynamic content. While nginx serves the static file, Apache is free to handle it’s dynamic files. Please correct me if I’m wrong!
March 15th, 2007 at 4:34 am
I use nginx as a proxy server for Apache Tomcat,and found that the performance is slow down to half of only running Tomcat,So I dont know why was that ?
The configuration like:
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
who can help me this
April 9th, 2007 at 10:24 am
Спасибо за статью! Жаль только ни слова не было сказано насчет апача, достаточно ли его только перевесить на другой порт (Listen :8080), и что-то еще нужно поправить?
А в конфиге nginx есть возможность построить условия (анализ HTTP-заголовков), на которых уже решать, что сделать с запросом, проксировать его апачу, или выдать 403?
June 10th, 2007 at 10:33 am
Статья отличная, но у меня не получается сделать так чтобы картинки отдавались в многопоточном режиме клиенту, т.е. они грузятся на странице по одной, я видел много ресурсов где явно видно что картинки отдаются по несколько сразу и отдаются они нгинксом, или такое только средствами nginx не реализовать.
June 15th, 2007 at 7:40 am
how to config the simple balancer
use nginx as frontend
use two tomcats as backend web servers
location /
proxy_pass
http://127.0.0.1:8080/;
http://127.0.0.1:9000/;
listen 80
June 22nd, 2007 at 12:07 pm
К сожалению данная схема не работает если на серваке крутятся виртуальные хосты, которые “сидят” на одном айпишнике. ((
Как быть в этой ситуации ?
Спасибо !
June 26th, 2007 at 4:33 am
Запустил вчера сервер с Вашим конфигом и сервак “умер”. Точнее начались такие тормоза что работать было просто невозможно.
У меня на серваке 8 виртуальных хостов, с которых раздаётся контент(музыка, кино и т.д.) Хотел при помощи нгинкс разгрузить апач, который временами виснет из-за огромного (около 2000) количества процессов. Перевесил каждый виртуальный хост на 127.0.0.1 на разные порты. Настроил нгинкс по Вашему примеру.
После запуска смог зайти более менее быстро только на один сайт. Побродить по нему и тем более что-то качнуть не удалось.((
Помогите разобраться в чём причина таких тормозов и как ускорить систему.
Система
Intel(R) Pentium(R) 4 CPU 2.40GHz
Память - 2 Гб
Ось -Fedora Core 5 - 2.6.20-1.2320.fc5
Apache - 2.2.2
Nginx - 0.5.26
Конфиг полностью совпадает с Вашим, за исключением папки root, конечно )
Жду ответа…
June 27th, 2007 at 8:44 pm
I’ve used tux on RH before to serve static content the same way(before apache), does any one know how much tux is faster/slower than nginx?
June 28th, 2007 at 12:59 pm
Hi!
Is’t possible to configure it to use DNS resolution for the backend servers?
I would like to have Nginx to relay http/https for many services on different servers in the backend, but not having to add seperate sections for each server/service.
Or will I lose something by doing that “if possible”?
July 26th, 2007 at 1:00 am
Is there any specific reason for using Apache as the behind server?
Why wouldn’t you have Nginx as the front and the backend server?
Is there any disadvantage to using Nginx for the dynamic content as well?
July 28th, 2007 at 4:24 pm
2 Egenius:
у меня крутится около полутора десятков виртуальных хостов через nginx и apache.
Nginx сидит на 80-м порту, apache - на 8080. Никаких проблем, всё отлично.
Очень большие тормоза были при первом заходе на сайт (после установки nginx как frontend) - сайт открывался больше двух минут. Но как только он открылся, всё стало работать очень шустро и быстро и до сих пор радует меня скоростью.
Конфиг - примерно такой же, как в статье, единственное, proxy_redirect использую.
Так что Вы, скорее всего, просто не до конца разобрались в конфигурации - советую обратиться к первоисточникам, и не использовать чужие конфиги.
August 14th, 2007 at 11:46 am
Добрый день.
А ктонибудь делал связку nginx + java?
August 24th, 2007 at 5:08 am
2 Egenius:
у меня была такая же ситуация. очень большой iowait.. оказалось что нагрузка сильно растет если отдавать файлы из пхп скриптов fopen, fread.. как только переделал XAccel нагрузка резко упала и использование нгинх оправдалось.
October 1st, 2007 at 2:23 pm
Доброго времени суток !
У меня такой вопросик …
Есть сайты на MS SharePoint`е в которих забиты внутрение адреса типа http://serv1.localnet/.
И есть сервак на FreeBSD с выходом в инет, который имеет свой адрес http://some.host.net/.
Возможно ли настроить nginx на замену адресов с http://serv1.localnet/ на http://some.host.net/ в страничках, и будет ли это так работать ?
October 2nd, 2007 at 6:56 am
hi.. thanks for all the great posts.
anyone ever configured nginx with haproxy? i would like to use nginx to serve static content and have haproxy load-balancing my mongrels serving 3 clusters. so that nginx gets request (serves if static) if not goes to HA for a proxy to the backend mongrel server.
October 2nd, 2007 at 3:42 pm
Fritzie: Why would you like to use haproxy for balancing when nginx has its own embedded balancing feature?
October 2nd, 2007 at 11:52 pm
doesn’t nginx use a round robin type of balancer. haproxy has an actual queue so its much better for lots of traffic. from what i understand about the queue is that it will only give to a mongrel cluster what it can handle.
October 21st, 2007 at 3:19 am
One of the things it keeps me worried about using a reverse proxy
is the reporting of visitors statistics.
Where will you take that information from? From the first (frontend)
web server? or from the servers behind it? What information will be
given? Will all the reports look like if the only visitor was the
reverse proxy server?
November 9th, 2007 at 8:49 am
Каково ограничение на максимальный размер отдаваемого файла?
December 18th, 2007 at 2:58 pm
Привет,
А есть способ сделать так, чтобы nginx вместо того, чтобы обслуживать:
location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {
root /spool/www/members_ng;
}
обслуживал все файлы, кроме .jsp и случая когде не указано расширение. Т.е. запрос к папке идёт.
Ну и папку /WEB-INF заоодно закрыть
December 25th, 2007 at 8:53 am
Менять в скриптах все же прийдется. Скажем взять PHP:
Таким образом, после редиректа, получится, что $HTTP_SERVER_VARS[PORT] = 8080, но это пол беды, т.к. это мало кому важно, гораздо страшнее следующая проблема:
При проксировании SSL мы получаем SERVER ENVIRONMENT
HTTPS = null
и
SERVER_PORT = 8080
При редиректе на какой-нибудь пеймент метод(не на все, но такое бывает), кастомер отредиректиться обратно(после проверки кредитки) на порт 8080. Плюс Corner of Trust и подобные штуки для верификации SSL-сертификата, внушающие доверие покупателям тоже могут не работать…
Решается такая проблема магическим RewriteRule’ом:
RewriteEngine on
RewriteCond %{HTTP:SSL} YES
RewriteRule .* - [E=HTTPS:on,L]
RewriteRule .* - [E=SERVER_PORT:443,L]
good luck
January 5th, 2008 at 9:55 pm
А разве точку в location не надо заслешить? Работать оно, конечно и так будет.
January 6th, 2008 at 12:10 pm
> anyone ever configured nginx with
> haproxy?
http://www.nginxhosting.com
January 21st, 2008 at 4:37 pm
не могу настроить слушать апач адрес 127.0.0.1:80
когда пишу
Listen 127.0.0.1:80
то он выдает ошибку
(98)Address already in use: make_sock: could not bind to address 0.0.0.0:80
no listening sockets available, shutting down
что делать?
January 23rd, 2008 at 7:02 pm
[...] should then fill it with the following configuration, courtesy of Alexey Kovyrin. Of course, you’ll need to change a few things to fit your specific setup, such as the domain [...]
February 5th, 2008 at 1:52 pm
Есть такая проблемка:
nginx, слушает somehost:6969
бэкэнд, на который перекидываются запросы
proxy_pass http://127.0.0.1:4850;
суть проблемы, бэкэнд посылает Location: /welcome, однако Proxy его перезаписывает как somehost/welcome, при этом теряется порт (6969)
собственно, что надо сделать с proxy_redirect, чтобы либо он оставался относительным, либо не терялся номер порта?
заранее спасибо
March 1st, 2008 at 4:11 pm
Everything works but I have done some benchmark tests with apache tool “ab” and nginx performs excellent with static files but when it has to proxy request to the Apache listening on 127.0.0.1:8080 for simple .php file it is drastically slower than Apache running solo.
Since, 70-80% of my sites are PHP based this practically dismisses nginx for me.
Or I am doing something wrong?
March 28th, 2008 at 6:16 am
[...] Начну с примера: есть сайт, который позволяет зарегистрированным пользователям скачивать что-либо (музыку, программы, фильмы — не суть важно). Одним из самых распространённых решений в этом случае является использование нескольких серверов. Во многих конфигурациях, которые я видел, “web-мордой” занимается Apache, а на обслуживании закачек стоит nginx+PHP+FastCGI (PHP занимается вопросами авторизации, ведения статистики и т.п.). Сразу оговорюсь, что есть альтернативное решение, когда nginx используется в качестве reverse proxy перед Apache — nginx проксирует запросы к PHP-скриптам Apache, а PHP-скрипт, если ему надо отдать что-то статическое, делает X-Accel-Redirect. Подробнее описано в статьях “Использование X-Accel-Redirect с Nginx для реализации контролируемых скачиваний” и “Использование Nginx Как Reverse-Proxy Сервера На Загруженных С…”. [...]
April 17th, 2008 at 7:24 am
Подскажите как при помощи nginx решить такую проблему: за nginx стоит apache, который в свою очередь периодически отключается мною. Хотелось бы чтобы во время выключения апача пользователи получали созданную мною html страничку с приличным текстом, а не страницу браузера, о том что не возможно подключиться к серверу.
location / {
proxy_pass http://localhost:8888/
….
….
}
May 19th, 2008 at 8:40 am
2Антон
Попробуй обработать 504 ошибку в nginx
June 7th, 2008 at 8:13 pm
[...] we decided to use nginx in what’s called a reverse-proxy. When you make a request to our Web server, nginx handles that request. It checks to see if the [...]
July 16th, 2008 at 2:45 pm
Статься прекрасная, но не полная.
Для полноты автору следовало бы описать и настройку Apache чтобы он не конкурировал с nginx, и нормально ловил подачи nginx