Comments 71
Схема стандартная, но верная. Еще бы добавить склейку js / css файлов в один js / css с трансляцией относительных путей на пути от корня и обновление сжатого файла автоматом, при обновлении несжатого.
Я бы добавил так: gzip_comp_level выставить на 9, прогнать любым скриптом для создания нагрузки задачу со списком статики и выставить на 5-6. В итоге получим максимальное сжатие статики и приемлимую нагрузку во время сжатия динамики.
Из выше-указанного непонятно почему нельзя использовать nginx для обработки php и отказаться от Apache, что освободит еще немного памяти, да и системных коннектов будет жрать в 2 раза меньше. Обычно установка nginx предполагает высокую нагрузку, если же mod_php отрабатывает долго то никакой nginx и lighttpd не поможет.

Автор пробовал lighttpd, при грамотной настройке он вел себя стабильнее чем nginx при обработке статики и динамики, по крайней мере ветка 1.4, и в нем также имеется сжатие статики.
Лишь предположу.
Дело в архитектуре nginx. Скажем nginx настроен на 8 воркеров. Это значит, что одновременно может исполняться только 8 скриптов. Остальны ждут своей очереди. При большом кол-во запросов и медленных скриптах, это очередь может быть очень длинной, и пользователь будет видеть лишь белую страницу.
Apache, наоборот, обрабатывает все скрпиты параллельно, лишь бы ресурсов хватило.
spanw-fcgi проблему решает чуть больше чем полностью. По крайней мере на lighttpd никаких проблем при 30-40 параллельных запросов на скрипты не было, всё работало быстро.
Ну так и nginx можно настроить так, чтобы он работал в связке со spawn-fcgi. В интернете полно мануалов.
Не сказал бы что это проще настраивать, чем поднять apache с php. И с Apache'м приходит много разных плюшек, по типу rewrite в .htaccess.
Во-первых, настроить не так и сложно, есть куча мануалов.
Во-вторых, реврайт настроить не проблема — есть и mod_rewrite (который настроить не тяжелее, чем аналог из Apache) и mod_magnet для более тяжелых случаев. Более того автор пишет
если ваш сайт использует mod_rewrite, то реврайты тоже можно делать на Nginx, а .htaccess файлы просто выкинуть

В-третьих, есть достаточно много плюшек и для lighttpd.
использовать nginx для обработки php и отказаться от Apache

Обрабатывать PHP прям внутри Nginx? Так он же асинхронный однопоточный…

Или вы все же про php-fpm/fcgi?
Прежние ветки лайти текли дай бог. Поэтому все давно на него забили и перешли на nginx.
Кроме того, какое-то время проект просто не развивался вообще, в том время как nginx почти еженедельно выпускал обновления.

> Автор пробовал lighttpd, при грамотной настройке он вел себя стабильнее чем nginx при обработке статики и динамики

Что значит «стабильнее», и какие ваши доказательства? :)
Стабильнее значит, что на продакшене у него было более быстрое время ответа и он не «залипал» периодически, как это часто было с Apache и реже с nginx. Например, на статическом сервере, который отдавал «потоковое» видео (mp4 и flv) и скрины к нему, nginx через некоторое время начинал отдавать даже мелкие картинки (4-5кб) по 5-10, на лайти такого замечено не было.
А есть аналогичная сжималка, но не на яве? Уж очень не хочется ее ставить на сервер.
Вы всегда можете заливать на сервер уже сжатые скрипты, задачи для сжатия css и js существуют для многих систем сборки, вот для Ant например. Еще есть вариант использовать расширение для Апача от Google — кроме возможностей по сжатию CSS и JS еще много функционала для ускорения сайта.
Спасибо.
У меня на одном сервере все формируется, а потом распределяется по нескольким, но на даже на первый сервер не хочу яву :)
При правильно настроенной конфигурации Nginx+Apache, когда статика отдается фронтом, рекомендую обязательно установить в Apache относительно небольшим MaxClients.

Нужно выбрать число таким, чтобы система не свопировала и оставалась память для MySQL и системы. Обычно достаточно 10-25. Увеличить таймаут на NGINX, чтобы он удерживал запросы и защищал бекэнд от перегрузки.
google closure compiler сжимает js лучше чем yuicompressor, особенно в advanced mode =)
UFO landed and left these words here
Хранить текст в Javascript'ах не комильфо, а длинные Unicode-последовательности кагбэ намекают на это ;-)
UFO landed and left these words here
Например, хранить отдельные файлы для языка/модуля с расширением .json

В плюсах:
— мультиязычность, с возможностью динамической смены языка
— основной скрипт одноразово сжимается с помощью GCC|gzip
— можно легко генерировать из php, а потом кешировать тем же nginx'ом

Минусы исходят из плюсов:
— отдельный файл, а значит требуется дополнительное время на его загрузку, хотя этим можно пренебречь
UFO landed and left these words here
UFO landed and left these words here
Сжимать .json с помощью GCC бессмысленно, ведь там будут в основном тексты, по-этому каждый русский символ будет 2 байтным, если кодировка UTF-8.
эти 6 символов как правило одни и те же по всему файлу, поэтому со свистом сжимаются гзипом в дофига и больше раз.
А нет ли решения, которое позволяло бы сжимать css/js на лету, кэшировать результат, и в следующий раз, если файл не изменился, отдавать из кэша?
UFO landed and left these words here
Спасибо. Неверно сформулировал вопрос — я имел в виду не compress, а minify.

В идеале хочется, чтобы файлы сжимались не по крону(мне вообще кажется это извращением, а вдруг надо что-то отредактировать внезапно, а оно минифицировано всё), а по требованию, и прозрачно.

Оригинальные файлы остаются без изменений, а минифицированные файлы лежат в .gz.
К тому же, nginx проверяет время модификации файла. Если оригинальный файл свежее, чем .gz, то отдаваться будет оригинальный файл.
Можно сделать rewrite добавляя .gz в конце, а на 404 = 200 и скрипт, который делает gz и отдает его же.
Проблема будет в том, что при реврайте на .gz файл, заголовок Content-Type будет соответствовать .gz файлу. В принципе можно сделать что-то вроде:
types { }
default_type application/javascript;

Но это делается в контексте location, поэтому придется писать location на каждый тип файла.
да будет дефолтовый
типы можно пропистаь и в контексте html. sample инклюдит mime.types именно там.
не знаю может и js.gz воспримется нормально, типа
application/x-javascript js js.gz;
Да, mime.types инклудится в контексте http (поправка). В контексте location это делается для того, чтобы переопределить типы:
location ~ \.js$ {
types { }
default_type application/javascript;
}

Прописывание application/x-javascript js js.gz; не помогает, только что проверил.
Да, тогда и в правду не стоит выпендриваться :)
и делать минификацию и сжатие по крону в gz, собирая nginx с модулем gzip_static
При разработке на ruby on rails я всегда пользуюсь jammit и не трачу время на сжатие и склеивание стилей и скриптов, расширение все делает за меня. При этом, если в системе доступна java, оно втоматически прогонит файлы через closure/yui compiler'ы.
С версией JRT 6 Update 22 (build 1.6.0_22-b04) yuicompressor-2.4.2 не дружит по ходу. Вчера заметил.
# java -version
java version «1.6.0_22»
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03, mixed mode)

Вот с этим работает.
мои 2 копейки:

1. ошибки лучше на продакшене закрывать статикой
error_page  404 500 501 502 503 504 /error.html;

location = /error.html {
        internal;
}


2. Для CMS с ЧПУ надо делать наоборот все в дефолтовом location а статитку по регулярке, ну и заглушка на техработы
try_files 	/maintenance.html @apache;
location @apache {
	proxy_intercept_errors 	on;
	# тут еще вставляем управление кэшем
	proxy_pass	http://127.0.0.1:8080;
}
location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|xml|swf)(\?.*)?$  {
	expires max;
}                                                         


3. заглушка для нежелательных файлов
location ~ /\.ht {
    deny  all;
}
пардон, спрошу нубские вопросы:
1. internal — означает, что nginx в случае ошибки при запросе к несуществующему example.com/aybabtu перенаправляет /error.html в корень example.com (т.е. example.com/error.html)?
2. обработка ошибок из первого случая не работает без proxy_intercept_errors из второго?
1. internal означает что запрос /error.html получит 404
2. верно, я его поэтому и оставил
подождите, но получается, что error_page 404 /error.html? но при запросе к /error.html получаем 404, значит, получаем /error.html?
получается что запрос к /error.html ничем не отличается от запроса к любому несуществующему урлу
Да содержимое будет из этого файла
1. internal означает что запрос /error.html получит 404
2. верно, я его поэтому и оставил
Черт, забыл
тогда пусть будет так:
        error_page  404 500 501 502 504 /error.html;

        location = /error.html {
                internal;
        }

        error_page 503 /maintenance.html;

        location /maintenance.html {
        	#pass
        }

        location / {

                if (-f $document_root/maintenance.html) {
                        return 503;
                }

                # далее по примерам
mod_rpaf работает некорректно. В частности перестают работать директивы allow from, deny from в .htaccess из-за того что не происходит подмены ip из X-Real-IP. Я использую mod_realip2, который полностью решил эту проблему.
Пока не нашел mod_realip2 так и делал. Но через .htaccess это делать удобнее. К тому же есть люди кроме меня, которым надо менять правила. Они имеют доступ к .htaccess, но не имеют доступа к настройкам хоста в nginx.
вообщем-то для полного офигения не хватает убрать отсюда апач, прикрутить оптимизацию картинок через www.smushit.com или через набор оптимизаторов
gzip_static по умолчанию в nginx отключен, и обычно надо пересобирать nginx чтобы ее использовать
Есть такое дело. Параметр --with-http_gzip_static_module для ./configure. В Gentoo Linux USE-флаг static-gzip.
Не понял принципиального отличия между моделью работы nginx и prefork Apache…
На 2-х ядерном процессое у nginx'а 2 потока, так же можно сконфигурировать Апач:
StartServers = 2
MinSpareServers = 2
MaxSpareServers = 2
MaxRequestsPerChild = 10000000…
запрос передавать на fastcgi — и получится тот же nginx?
Дело в том, что поток Apache занимается лишь одним клиентом — такая архитектура. Поток же nginx в цикле пробегает по коннектам и уделяет каждому понемногу времени. Объясняю своими словами, надеюсь корректно описал суть :)
а апач как это делает?
я так понял, что это работает приерно так: процесс получил, запрос, передал его fastCGI, получил следующий, передал, получил результат от fastCGI, передал его сокету, полуил запрос на статику, считал, передал сокету… и т.д. В чём тогда разница между nginx и prefork Apache?
Один поток Apache делает вот что: получает запрос от клиента, обрабатывает запрос, выдает результат клиенту. Один поток занимается одним клиентом и больше ничем. Т.е. с параметрами, которые Вы привели выше, Apache не сможет обработать более двух клиентов параллельно.
А один поток nginx работает иначе: в бесконечном цикле он пробегается по массиву сокетов, при необходимости считывает/записывает небольшой блок данных из/в сокет(а). Т.е. за каждый цикл он обслуживает сразу кучу клиентов (не более значения опции worker_connections). Это принцип работы poll. epoll работает еще эффективнее, но суть примерно такая же.
Использование NGINX перед апачем имеет одну проблему. которую нужно иметь ввиду.
Иногда некоторые криворукие программисты делают из флэшек запросы на получение других флэшек методом GET.
Apache такие запросы обрабатывает нормально. а вот nginx их не разрешает.
Т.е. если вы берёте абстрактнгый веб проект и хотите его ускорить, то без переписывания кусков флэша — может не обойтись.
+ Не забывайте что использование front'end'a автоматически лишит вас информации об IP пользователя. и вам придется обязательно в настройках NGINX позаботится о правильной конверсии header'ов
ошибка в посте… не GET a POST
следует читать
>>Иногда некоторые криворукие программисты делают из флэшек запросы на получение других флэшек методом POST.
почему в пресловутом абстрактном веб-проэкте вообще не отказаться от использования апача?

nginx прекрасно справляется и с отдачей статики, и с обработкой динамики на фастцги сервере. для чего нужен то апач?
# Включаем модуль
RPAFenable On
# Доводит до ума X-Host
RPAFsethostname On
# Адрес фронтенда (nginx)
RPAFproxy_ips ТУТ.ВАШ.IP.АДР 127.0.0.1
# Имя отправляемого заголовка
RPAFheader X-Forwarded-For
Only those users with full accounts are able to leave comments. Log in, please.