nginx и gzip_static: еще один способ снизить нагрузку на сервер
Отдача предварительно сжатых файлов для снижения нагрузки на процессор
Чем меньше размер страниц сайта, тем меньше расход трафика, загрузка канал и выше скорость загрузки страниц. Один из самых распространённых способов уменьшения страниц — сжатие перед отправкой пользователю.
В Apache для этих целей используется mod_deflate, в nginx — ngx_http_gzip_module.html. В других web-серверах используются похожие решения.
Что mod_deflate, что ngx_http_gzip_module используют сжатие «на лету» — файл сжимается перед отдачей пользователю. Но сжатие — операция, нагружающая процессор, и чем выше степень сжатия, тем больше нагрузка. Это не было бы проблемой, если бы один и тот же файл не приходилось сжимать каждый раз заново.
Для nginx есть простой вариант, который позволяет избежать повторного сжатия — использование модуля ngx_http_gzip_static_module. Но этот модуль по умолчанию не собирается — поэтому нужно разрешить его сборку путём передачи параметра --with-http_gzip_static_module скрипту configure.
Включается модуль путём добавления директивы gzip_static on; в блок http или виртуальный хост, после чего nginx будет отдавать вместо обычного файла предварительно сжатый файл с таким же именем и дополнительным расширением .gz. То есть если есть файл index.html.gz, то nginx будет отдавать его при запросе к файлу index.html.
Дело осталось за малым — сжать все статические файлы. И задать им ту же дату модификации, что у исходного файла.
Вручную это делается так:
touch -r index.html index.html.gz
Но сжимать все файлы вручную — это скучно и муторно. Можно воспользоваться двумя скриптами:
EXTENSIONS="txt|html?|css|js|xml|ico|patch|diff|c"
if [ -z "$1" ]; then
DIR="`pwd`"
else
DIR="$1"
fi
find $DIR -type f -regextype posix-egrep -regex ".*\.($EXTENSIONS)\$" -exec `dirname $0`/do-compress.sh '{}' \;
и
MINSIZE=100
GZIP="gzip -9 -c"
AWK=awk
TOUCH=touch
if [ -n "$1" ]; then
GZ_NAME="$1.gz"
DATA_PLAIN=`stat --format "%s %Y" "$1"`
PLAIN_SIZE=`echo "$DATA_PLAIN" | $AWK '{ print $1}'`
PLAIN_MTIME=`echo "$DATA_PLAIN" | $AWK '{ print $2}'`
if [ $PLAIN_SIZE -lt $MINSIZE ]; then
echo "Ignoring file $1: its size ($PLAIN_SIZE) is less than $MINSIZE bytes"
exit 0;
fi
if [ -f "$GZ_NAME" ]; then
GZIPPED_MTIME=`stat --format "%Y" "$GZ_NAME"`
if [ $GZIPPED_MTIME -eq $PLAIN_MTIME ]; then
echo "Ignoring file $1: there is a compressed file $GZ_NAME with the same modification time"
exit 0
fi
fi
$GZIP -9 -c "$1" > "$GZ_NAME"
$TOUCH -r "$1" "$GZ_NAME"
echo "Compressed $1 to $GZ_NAME"
fi
Файлы нужно поместить в один и тот же каталог, сделать исполняемыми (chmod 0755 compress.sh do-compress.sh) и немного настроить.
В файле compress.sh задаётся список расширений (регулярным выражением) файлов, которые нужно сжимать:
Для тех, кто с регулярными выражениями не знаком, есть простое правило: новые расширения разделяются вертикальной чертой. Иными словами, если нужно сжимать файлы с расширением .svg, то строка выше примет следующий вид:
В файле do-compress.sh единственным параметром, который, вероятно, придется изменить, является MINSIZE. Он задаёт минимальный размер (в байтах) файла, который стоит сжимать. По умолчанию это 100 байт, по идее, должно быть нормально.
Запускается скрипт так (предполагая, что он находится в текущем каталоге):
Параметр, передаваемый скрипту — это путь к каталогу, где находится блог (сайт): скрипт рекурсивно обработает все подкаталоги.
Скрипт нужно запускать каждый раз (да, есть такой недостаток), когда изменился/добавился какой-либо подходящий для сжатия файл. Например, если вы изменили файл со стилями темы WordPress. Скрипт не будет пытаться сжимать файл, если существует сжатый файл с одинаковым временем последнего изменения — при последующих запусках будут сжиматься только новые и изменённые файлы. Что значительно снижает ресурсоёмкость процесса.
После всех манипуляций nginx будет отдавать заранее сжатые файлы, что позволит снизить нагрузку на процессор.
Разочарую всех тех, кто думает, что снижение нагрузки будет кардинальным: вряд ли. Но всё зависит от железа. Чем меньше мощность сервера, тем больше снижение нагрузки.
Связанные записи
Автор: Vladimir; опубликовано в: WordPress, Администрирование; метки: nginx, WordPress, нагрузка, сжатие, трафикНоя
2009


Меня зовут Владимир, я программист-фрилансер, специализирующийся на Web-программировании и програмировании под Linux.
По совместительству занимаюсь администрированием LAMP/LNMP-серверов и техническим переводом.






Спасибо за статью.
Посмотреть, если в Вашей версии поддержка “ngx_http_gzip_static_module” можно в выводе команды nginx -V
У меня ошибка вылезла:
find: invalid predicate `-readable’
Пришлось этот параметр затереть, без него всё нормально сработало.
FreeBSD?
CentOS 5.4 и на Gentoo пробывал.
Ошибка одна и та-же.
Ещё кстати вопросик в голове возник:
У меня в nginx.conf gzip с 5-м уровнем компрессии стоит (слабый VDS): gzip_comp_level 5;
А в ручную я сжал с 9-м уровнем.
Вопрос: Он пережимать файлы будет из-за разной степени сжатия или он сразу готовый, сжатый файл отдаёт?
Всегда будет отдавать готовый файл. Даже если исходный изменится. Поэтому при изменении исходного файла его нужно пережимать.
Я у себя этот скрипт вообще на крон повесил.
А к чему жать HTML? Если они часто меняются и их постоянно нужно пережимать, то это уже лишнее, nginx налету их жмет нормально и нагрузку создать почти не успевает
Сжатие выше 5 тоже лишнее, реальной пользы от 9 мало.
При большом количестве html файлов на винте, будет проще прописать
root /home/user/site.com;
expires 1d;
error_page 404 = @fallback;
}
Так дело до Apache совсем не дойдет.
Оправдано жать только css и js
Статика редко изменяется (хотя всегда есть исключения).
Идея в том, чтобы не заставлять nginx сжимать файлы на лету, а вместо этого отдавать заранее сжатый файл. Спички, но всё же. Я сейчас собираю статистику, но пока не проанализирую логи, ничего конкретно сказать не могу. Хотя чисто визуально на графике munin средняя загрузка системы чуть меньше.
А смысл вообще в nginx, если статика отдаётся Апачу? Обычно nginx отдаёт статику, а запросы к PHP проксирует Апачу. Хотя если стоит nginx, то Апач вообще не нужен
Согласен, в основном они и создают нагрузку.
PS — Ваш регэксп можно чуть упростить:
\.(css|js|html)$