apache+nginx+gzip_static+yuicompressor
В этой статье я опишу принципиальные различия Apache и Nginx, архитектуру фронтэнд-бэкэнд, установку Apache в качестве бэкэнда и Nginx в качестве фронтэнда. А также опишу технологию, позволяющую ускорить работу веб-сервера: gzip_static+yuicompressor.
Nginx
Nginx – сервер легкий; он запускает указанное число процессов (обычно число процессов = числу ядер), и каждый процесс в цикле принимает новые соединения, обрабатывает текущие. Такая модель позволяет с низкими затратами ресурсов обслуживать большое количество клиентов. Однако, при такой модели, нельзя выполнять длительные операции при обработке запроса (например mod_php), т.к. это по сути повесит сервер. При каждом цикле внутри процесса по сути выполняются две операции: считать блок данных откуда-то, записать куда-то. Откуда-то и куда-то – это соединение с клиентом, соединение с другим веб-сервером или FastCGI-процессом, файловая система, буфер в памяти. Модель работы настраивается двумя основными параметрами:
- worker_processes – число запускаемых процессов. Обычно устанавливают равным числу ядер процессора.
- worker_connections – максимальное число соединений, обрабатываемых одним процессом. Напрямую зависит от максимального числа открытых файловых дескрипторов в системе (1024 по умолчанию в Linux).
Apache
Apache – сервер тяжелый (следует заметить, что при желании его можно достаточно облегчить, однако это не изменит его архитектуры); он имеет две основных модели работы – prefork и worker.
При использовании модели prefork Apache создает новый процесс для обработки каждого запроса, и этот процесс выполняет всю работу: принимает запрос, генерирует контент, отдает пользователю. Настраивается эта модель следующими параметрами:
- StartServers – задает число запускаемых процессов при старте веб-сервера.
- MinSpareServers – минимальное число висящих без дела процессов. Нужно это для того, чтобы при поступлении запроса быстрее начать его обрабатывать. Веб-сервер будет запускать дополнительные процессы, чтобы их было указанное количество.
- MaxSpareServers – максимальное число висящих без дела процессов. Это нужно, чтобы не занимать лишнюю память. Веб-сервер будет убивать лишние процессы.
- MaxClients – максимальное число параллельно обслуживаемых клиентов. Веб-сервер не запустит более указанного количества процессов.
- MaxRequestsPerChild – максимальное число запросов, которые обработает процесс, после чего веб-сервер убьет его. Опять же, для экономии памяти, т.к. память в процессах будет постепенно "утекать".
Эта модель была единственной, которую поддерживал Apache 1.3. Она стабильная, не требует от системы многопоточности, но потребляет много ресурсов и немного проигрывает по скорости модели worker.
При использовании модели worker Apache создает несколько процессов, по несколько потоков в каждом. При этом каждый запрос полностью обрабатывается в отдельном потоке. Чуть менее стабильна, чем prefork, т.к. крах потока может привести к краху всего процесса, но работает немного быстрее, потребляя меньше ресурсов. Настраивается эта модель следующими параметрами:
- StartServers – задает число запускаемых процессов при старте веб-сервера.
- MinSpareThreads – минимальное число потоков, висящих без дела, в каждом процессе.
- MaxSpareThreads – максимальное число потоков, висящих без дела, в каждом процессе.
- ThreadsPerChild – задает число потоков, запускаемых каждым процессом при старте процесса.
- MaxClients – максимальное число параллельно обслуживаемых клиентов. В данном случае задает общее число потоков во всех процессах.
- MaxRequestsPerChild – максимальное число запросов, которые обработает процесс, после чего веб-сервер убьет его.
Фронтэнд-бэкэнд
Основная проблема Apache – на каждый запрос выделен отдельный процесс (как минимум – поток), который к тому же увешан различными модулями и потребляет немало ресурсов. Вдобавок, этот процесс будет висеть в памяти до тех пор, пока не отдаст весь контент клиенту. Если у клиента узкий канал, а контент достаточно объемный, то это может занять длительное время. Например, сервер сгенерирует контент за 0,1 сек, а отдавать клиенту его будет 10 сек, все это время занимая системные ресурсы.
Для решения этой проблемы используется архитектура фронтэнд-бэкэнд. Суть ее в том, что запрос клиента приходит на легкий сервер, с архитектурой типа Nginx (фронтэнд), который перенаправляет (проксирует) запрос на тяжелый сервер (бэкэнд). Бэкэнд формирует контент, очень быстро его отдает фронтэнду и освобождает системные ресурсы. Фронтэнд кладет результат работы бэкэнда в свой буфер и может долго и упорно отдавать его (результат) клиенту, потребляя при этом намного меньше ресурсов, чем бэкэнд. Дополнительно фронтэнд может самостоятельно обрабатывать запросы статических файлов (css, js, картинки и т.д.), управлять доступом, проверять авторизацию и т.д.
Настройка связки Nginx (фронтэнд) + Apache (бэкэнд)
Предполагается, что Nginx и Apache у вас уже установлены. Необходимо настроить сервера так, чтобы они слушали разные порты. При этом, если оба сервера установлены на одной машине, бэкэнд лучше вешать только на loopback-интерфейс (127.0.0.1). В Nginx это настраивается директивой listen:
listen 80;
В Apache это настраивается директивой Listen:
Listen 127.0.0.1:81
Далее нужно указать Nginx проксировать запросы на бэкэнд. Это делается директивой proxy_pass http://127.0.0.1:81;. Это вся минимальная конфигурация. Однако выше мы говорили, что отдачу статических файлов лучше тоже поручить Nginx. Допустим, что у нас типичный сайт на PHP. Тогда нам нужно проксировать на Apache только запросы к .php файлам, обрабатывая все остальное на Nginx (если ваш сайт использует mod_rewrite, то реврайты тоже можно делать на Nginx, а .htaccess файлы просто выкинуть). Также необходимо учесть, что запрос клиента приходит на Nginx, а запрос к Apache делает уже Nginx, поэтому HTTP-заголовка Host не будет, а адрес клиента (REMOTE_ADDR) Apache определит как 127.0.0.1. Заголовок Host подставить несложно, а вот REMOTE_ADDR Apache определяет сам. Решается эта проблема при помощи mod_rpaf для Apache. Работает он следующим образом: Nginx знает IP клиента и добавляет некий HTTP-заголовок (например X-Real-IP), в который прописывает этот IP. mod_rpaf получает этот заголовок и прописывает его содержимое в переменную REMOTE_ADDR Apache. Таким образом, php-скрипты, выполняемые Apache будут видеть реальный IP клиента.
Теперь конфигурация усложнится. Сначала позаботьтесь, чтобы и в Nginx, и в Apache существовал один и тот же виртуальный хост, с одинаковым корнем. Пример для Nginx:
server { listen 80; server_name example.com; root /var/www/example.com/; }
Пример для Apache:
<VirtualHost 127.0.0.1:81> DocumentRoot "/var/www/example.com/" ServerName example.com </VirtualHost>
Теперь задаем настройки для вышеописанной схемы:
Nginx:
server { listen 80; server_name example.com; location / { root /var/www/example.com/; index index.php; } location ~ \.php($|\/) { proxy_pass http://127.0.0.1:81; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; } }
Apache:
# настройки mod_rpaf RPAFenable On RPAFproxy_ips 127.0.0.1 RPAFheader X-Real-IP <VirtualHost 127.0.0.1:81> DocumentRoot "/var/www/example.com/" ServerName example.com </VirtualHost>
Регулярное выражение \.php($|\/) описывает две ситуации: запрос к *.php и запрос к *.php/foo/bar. Второй вариант необходим для работы многих CMS. При запросе example.com/ запрос будет переписан в example.com/index.php (т.к. мы определили index-файл) и также будет проксирован на Apache.
Ускоряемся: gzip_static+yuicompressor
Gzip в Web это хорошо. Текстовые файлы отлично сжимаются, трафик экономится, и контент быстрее доставляется пользователю. Nginx умеет сжимать на лету, так что тут проблем нет. Однако на сжатие файла тратится определенное время, в том числе процессорное. И тут на помощь приходит директива Nginx gzip_static. Суть ее работы в следующем: если при запросе файла Nginx находит файл с таким же именем и дополнительным расширением ".gz", например, style.css и style.css.gz, то вместо того, чтобы сжимать style.css, Nginx прочитает с диска уже сжатый style.css.gz и отдаст его под видом сжатого style.css.
Настройки Nginx будут выглядеть так:
http { ... gzip_static on; gzip on; gzip_comp_level 9; gzip_types application/x-javascript text/css; ...
Прекрасно, мы один раз будем генерировать .gz файл, чтобы Nginx много раз его отдал. А дополнительно мы будем сжимать css и js при помощи YUI Compressor. Эта утилита максимально минимизирует css и js файлы, удаляя пробелы, сокращая наименования и т.д.
А заставить все это сжиматься автоматически, да еще и обновляться автоматически можно при помощи cron и небольшого скрипта. Пропишите в cron для запуска раз в сутки следующую команду:
/usr/bin/find /var/www -mmin 1500 -iname "*.js" -or -iname "*.css" | xargs -i -n 1 -P 2 packfile.sh
в параметре -P 2 укажите число ядер вашего процессора, не забудьте прописать полный путь к packfile.sh и изменить /var/www на ваш веб-каталог.
В файл packfile.sh пропишите:
java -jar /var/www/gzip/yuicompressor-2.4.2.jar "$1" | gzip -c -9 > "$1.gz"
не забудьте указать правильный путь к yuicompressor-2.4.2.jar.
Это все, готов выслушать критику :)
См. также: Ускорение PHP при помощи APC и Memcache для сессий.
6 комментариев
Комментарий от: Peter
Разница есть, но она небольшая. Однако, если небольшое снижение нагрузки на сервер может быть несущественно, то даже небольшое увеличение скорости загрузки имеет большое значение.
Комментарий от: Сергей
А какие-то данные до и после можете привести ? На какой OS делали ?
Комментарий от: Peter
На Linux. Цифр никаких нет, постараюсь на досуге провести тесты и опубликовать результаты.
After looking for a long time something about this Google brought me to your doorsteps. Praise the Lord! Thank you Google for helping me, also, thank you so much for gathering so many information’s. Love your post and will check your site often! Thanks
Комментарий от: barbour outlet sale
He will not provide you with an estimate of his barbour sale charges even if you ask for it. He will convince you to hire him without an estimate and once you hire, he starts revealing the horror side of him. After you hire him, he will abuse you and ask you to pay hidden fees and charges barbour sale uk that are absurd.. Among all the dress up style, men’s ties always plays a vital part for the appearance of men. You can barbour sale uk feel the warmth of your energy as it flows down your back
Идет загрузка формы...
Комментарий от: Alex Samorukov
если не секрет - почувствовали ли вы разницу с gzip static в LA и/или в latency? На моих проектах обычно на nginx нагрузка минимальная, если сравнивать с другими компонентами, потому и спрашиваю.