porsche2
Мой дом здесь!
- Регистрация
- 18 Ноя 2007
- Сообщения
- 669
- Реакции
- 234
- Автор темы
- #1
Файловое кеширование NGINX+MD5
В общем озадачился я полнотекстовым (файловым) кешированием на VDS для сайтов на CMS Vivvo, хотя для полнотекстового кеширования движок не важен, поэтому мой метод подойдет всем желающим.
План действий примерно такой:
1. При первом обращении к странице создать кеш
2. Сжать кеш-файл Gzip-ом и положить туда же
3. Заставить Nginx проверять кеш, и при включенном gzip в браузере, отдавать сжатый файл если он есть (gzip_static).
4. Чистить кеш с нужной периодичностью
Все ссылки на сайте лучше всего привести к SEO_URL виду, (site.com/article/1.html… site.com/category/1.html… site.com/rss.xml )
Итак:
1. Создаем кеш-файл, добавляем в index.php:
[/spoil]
2. Жмем то, что еще не сжато и выравниваем время
compress.sh
[spoil]
[/spoil]
do-compress.sh
[spoil]
(скрипт сжатия с блога Для просмотра ссылки Войдиили Зарегистрируйся)
Запускается так:
Прописываем в CRON с нужной периодичностью такую строку
/scripts/compress.sh /home/...ПУТЬ.../site.com/cache_files >/dev/null 2>&1
Естественно в /scripts лежат файлы compress.sh и do-compress.sh с правами на исполнение. Есть конечно что доработать, например искать несжатые файлы которые не старше получаса или двух-трех минут, чтобы не колбасить все, но это уже нюансы.
3. Теперь собственно самое интересное, nginx работает как прокси и при наличии кеша, он не должен дергать php и проксировать, а должен искать кеш и лучше уже сжатый (gzip_static on;). Фалы лежат .../site.com/cache_files/
В nginx.conf в диррективу http добавляем
http {
perl_set $md5_uri 'sub {
use Digest::MD5 qw(md5_hex);
my $r = shift;
my $uri=$r->uri;
my $args=$r->args;
if ($args){
$uri=$uri."?".$args;
}
$md5 = md5_hex($uri);
return $md5;
}';
…
…
И теперь в конфигурацию сайта в первый location добавляем
location / {
proxy_pass Х_Х_ttp://1.2.3.4:8080;
…
…
try_files /cache_files/$md5_uri.html @fallback;
#в случае если в uri попали параметры, например site.com/article/1.html?YoHoHo
# тогда получим 301 редирект site.com/article/1.html
if ($args) {return 301 Для просмотра ссылки Войдиили Зарегистрируйся
if ($request_uri != $uri) {
#return 403;
return 301 Для просмотра ссылки Войдиили Зарегистрируйся
#Это нужно для того, чтобы в случае запроса site.com/article/1.html? срабатывал редирект или выдавало ошибку. Сделано потому, что nginx такой запрос обработает без вопроса (?), так как параметров нет.
}
В некоторых случаях требуется костыль, когда кеширования нет (нет MD5_URI), я костыль сделал таким:
location /plugins/ {
try_files $uri @fallback;
#error_log /var/log/nginx/error.log;
expires -1;
}
4. Убиваем старый кеш, я чищу по крону
delite60.sh
Запускается так:
Прописываем в CRON с нужной периодичностью такую строку
/scripts/delite60.sh /home/...ПУТЬ.../site.com/cache_files >/dev/null 2>&1
Проверяем:
Идем на site.com/index.php и в директории .../site.com/cache_files появляется файл ab25467rakodabra.html
В первом location / затираем @fallback
try_files /cache_files/$md5_uri.html;
командуем: killall nginx -HUP
Опять заходим на site.com, если видим страницу, а другие URI не работают, значит все отлично. Кстати подобной конструкции (error_page 404 502 = @fallback; ) тоже быть не должно, а то я себе чуть весь мозг не высек
Далее проверяем gzip_static
Берем файл ab25467rakodabra.html копируем в папку ../tmp, дописываем в него метку Hello Gzip, сжимаем - ab25467rakodabra.html.gz кидаем его в .../site.com/cache_files, и командуем
find /путь/site.com/cache_files "*.*" -exec touch -t201204032300 {} \;
Снова идем на site.com и если видим метку Hello Gzip значит gzip_static работает как надо. Возвращаем @fallback + killall nginx -HUP . Теперь осталось только подправить конфиг под все location (а это иногда абзац). Сидим и радуемся.
При средней загрузке HDD, такое файловое кеширование работает быстрее или равноценно кешированию в оперативке (xcache и memcache …) выигрыш идет за счет сокращение цепочки «Запрос-РезультатКРУТОЙсЖАТЫЙ», в итоге нагрузка на процессор минимальная, лишний раз не дергается php, apache, БД. Оперативка свободна и ее можно использовать под хранение session или кеширования тяжелых запросов в БД.
Если сайт интерактивный, комментарии и прочая лабуда, то AJAX всех спасет. А так как нагрузка на HDD выросла… наверное ( не мерил), то кеширование на клиенте и минимизация запросов не плохо сгладит этот угол, и VDS можно будет упаковать плотнее.
P.S. Ругайтесь тише
В общем озадачился я полнотекстовым (файловым) кешированием на VDS для сайтов на CMS Vivvo, хотя для полнотекстового кеширования движок не важен, поэтому мой метод подойдет всем желающим.
План действий примерно такой:
1. При первом обращении к странице создать кеш
2. Сжать кеш-файл Gzip-ом и положить туда же
3. Заставить Nginx проверять кеш, и при включенном gzip в браузере, отдавать сжатый файл если он есть (gzip_static).
4. Чистить кеш с нужной периодичностью
Все ссылки на сайте лучше всего привести к SEO_URL виду, (site.com/article/1.html… site.com/category/1.html… site.com/rss.xml )
Итак:
1. Создаем кеш-файл, добавляем в index.php:
Код:
// файловое кэширование страниц
$settings_cachedir = $_SERVER['DOCUMENT_ROOT'].'/cache_files/';
$thispage = $_SERVER['REQUEST_URI'];
$cachelink = $settings_cachedir.md5($thispage).".html";
if (file_exists($cachelink)) {
readfile($cachelink);die();
}
ob_start();
.........
.........
.........
//
$fp = fopen($cachelink, 'w');
fwrite($fp, ob_get_contents());
fclose($fp);
ob_end_flush();
// конец файового кэширование страниц
2. Жмем то, что еще не сжато и выравниваем время
compress.sh
[spoil]
Код:
#! /bin/sh
EXTENSIONS="txt|html?|css|js|xml"
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 '{}' \;
exit 0
do-compress.sh
[spoil]
Код:
#! /bin/sh
MINSIZE=100
GZIP="gzip -7 -c -n"
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 -7 -c "$1" > "$GZ_NAME"
$TOUCH -r "$1" "$GZ_NAME"
echo "Compressed $1 to $GZ_NAME"
fi
(скрипт сжатия с блога Для просмотра ссылки Войди
Запускается так:
Прописываем в CRON с нужной периодичностью такую строку
/scripts/compress.sh /home/...ПУТЬ.../site.com/cache_files >/dev/null 2>&1
Естественно в /scripts лежат файлы compress.sh и do-compress.sh с правами на исполнение. Есть конечно что доработать, например искать несжатые файлы которые не старше получаса или двух-трех минут, чтобы не колбасить все, но это уже нюансы.
3. Теперь собственно самое интересное, nginx работает как прокси и при наличии кеша, он не должен дергать php и проксировать, а должен искать кеш и лучше уже сжатый (gzip_static on;). Фалы лежат .../site.com/cache_files/
В nginx.conf в диррективу http добавляем
http {
perl_set $md5_uri 'sub {
use Digest::MD5 qw(md5_hex);
my $r = shift;
my $uri=$r->uri;
my $args=$r->args;
if ($args){
$uri=$uri."?".$args;
}
$md5 = md5_hex($uri);
return $md5;
}';
…
…
И теперь в конфигурацию сайта в первый location добавляем
location / {
proxy_pass Х_Х_ttp://1.2.3.4:8080;
…
…
try_files /cache_files/$md5_uri.html @fallback;
#в случае если в uri попали параметры, например site.com/article/1.html?YoHoHo
# тогда получим 301 редирект site.com/article/1.html
if ($args) {return 301 Для просмотра ссылки Войди
if ($request_uri != $uri) {
#return 403;
return 301 Для просмотра ссылки Войди
#Это нужно для того, чтобы в случае запроса site.com/article/1.html? срабатывал редирект или выдавало ошибку. Сделано потому, что nginx такой запрос обработает без вопроса (?), так как параметров нет.
}
В некоторых случаях требуется костыль, когда кеширования нет (нет MD5_URI), я костыль сделал таким:
location /plugins/ {
try_files $uri @fallback;
#error_log /var/log/nginx/error.log;
expires -1;
}
4. Убиваем старый кеш, я чищу по крону
delite60.sh
Код:
#! /bin/sh
if [ -z "$1" ]; then
DIR="`pwd`"
else
DIR="$1"
fi
find $DIR -mmin +60 -type f -exec rm -rf {} \;
Запускается так:
Прописываем в CRON с нужной периодичностью такую строку
/scripts/delite60.sh /home/...ПУТЬ.../site.com/cache_files >/dev/null 2>&1
Проверяем:
Идем на site.com/index.php и в директории .../site.com/cache_files появляется файл ab25467rakodabra.html
В первом location / затираем @fallback
try_files /cache_files/$md5_uri.html;
командуем: killall nginx -HUP
Опять заходим на site.com, если видим страницу, а другие URI не работают, значит все отлично. Кстати подобной конструкции (error_page 404 502 = @fallback; ) тоже быть не должно, а то я себе чуть весь мозг не высек
Далее проверяем gzip_static
Берем файл ab25467rakodabra.html копируем в папку ../tmp, дописываем в него метку Hello Gzip, сжимаем - ab25467rakodabra.html.gz кидаем его в .../site.com/cache_files, и командуем
find /путь/site.com/cache_files "*.*" -exec touch -t201204032300 {} \;
Снова идем на site.com и если видим метку Hello Gzip значит gzip_static работает как надо. Возвращаем @fallback + killall nginx -HUP . Теперь осталось только подправить конфиг под все location (а это иногда абзац). Сидим и радуемся.
При средней загрузке HDD, такое файловое кеширование работает быстрее или равноценно кешированию в оперативке (xcache и memcache …) выигрыш идет за счет сокращение цепочки «Запрос-РезультатКРУТОЙсЖАТЫЙ», в итоге нагрузка на процессор минимальная, лишний раз не дергается php, apache, БД. Оперативка свободна и ее можно использовать под хранение session или кеширования тяжелых запросов в БД.
Если сайт интерактивный, комментарии и прочая лабуда, то AJAX всех спасет. А так как нагрузка на HDD выросла… наверное ( не мерил), то кеширование на клиенте и минимизация запросов не плохо сгладит этот угол, и VDS можно будет упаковать плотнее.
P.S. Ругайтесь тише