Файловое кеширование NGINX+MD5

porsche2

Мой дом здесь!
Регистрация
18 Ноя 2007
Сообщения
669
Реакции
234
Файловое кеширование 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:


Код:
// файловое кэширование страниц
$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();
 
// конец файового кэширование страниц
[/spoil]





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
[/spoil]



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. Ругайтесь тише
 
Добрый день. Следовал инструкциям из Вашей темы Файловое кеширование NGINX+MD5 и получил ошибку. Подскажите пожалуйста если не сложно, что может быть не так, после пункта
В nginx.conf в диррективу http добавляем
http {
perl_set $md5_uri 'sub {
У меня ошибка
nginx: [emerg] unknown directive "perl_set" in /etc/nginx/nginx.conf:32
nginx: configuration file /etc/nginx/nginx.conf test failed
В чем может быть проблема?
Спасибо
 
Наверно нет модуля ngx_http_perl_module
Для просмотра ссылки Войди или Зарегистрируйся

Для проверки что включено в nginx и версию
Код:
nginx -V

Затем проверяете есть perl_module
 
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-file-aio --with-threads --with-ipv6 --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables'
[root@vm3440 ~]#
Получается нет, буду читать как установить. Спасибо, если что можно еще обращаться?
 
А не подскажите как его подключит. По всей видимости установлен, а как подключит, облазил в интернете не нашел, точнее не понял. Вот что есть его сборку необходимо разрешить с помощью конфигурационного параметра --with-http_perl_module. Где этот параметр находится? Спасибо

This is perl, v5.10.1 (*) built for i386-linux-thread-multi

Copyright 1987-2009, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at Для просмотра ссылки Войди или Зарегистрируйся, the Perl Home Page.
 
Нужно собрать из исходников и при компиляции указать параметр --with-http_perl_module
Примерно по этому руководству нужно делать Для просмотра ссылки Войди или Зарегистрируйся
Скачивать нужно последнюю стабильную версию Для просмотра ссылки Войди или Зарегистрируйся
Только скрипт инициализации нужно будет добавить как в руководстве написано.
Создайте скрипт инициализации, который будет запускать / останавливать Nginx. Вы можете скачать скрипт для различных сред Linux с Для просмотра ссылки Войди или Зарегистрируйся.


Или лучше не удалять уже установленный Nginx потому что скрипт запуска сервера будет нужен.
Вот по этому руководству лучше делайте Для просмотра ссылки Войди или Зарегистрируйся В этом руководстве добавляли более новый OpenSSL, вы добавляйте нужный модуль.
Всё что нужно для компиляции установите из первого руководства
Код:
apt-get install build-essential zlib1g-dev libpcre3-dev libssl-dev libxslt1-dev libxml2-dev libgd2-xpm-dev libgeoip-dev libgoogle-perftools-dev libperl-dev
 
Последнее редактирование:
Добрый вечер. С горем пополам удалось подключить perl. Теперь другая проблема, когда вношу try_files /cache_files/$md5_uri.html @fallback; сайт не открывается, в чем может быть причина? Получается так у меня:

server {
listen 185.53.169.64:80;
server_name kino24-7.ru Для просмотра ссылки Войди или Зарегистрируйся
error_log /var/log/httpd/domains/kino24-7.ru.error.log error;

location / {
proxy_pass Для просмотра ссылки Войди или Зарегистрируйся

proxy_cache kino24-7.ru;
proxy_cache_valid 15m;
proxy_cache_valid 404 1m;
proxy_no_cache $no_cache;
proxy_cache_bypass $no_cache;
proxy_cache_bypass $cookie_session $http_x_update;
try_files /cache_files/$md5_uri.html @fallback;

location ~* ^.+\.(jpg|jpeg|gif|png|ico|svg|css|zip|tgz|gz|rar|bz2|exe|pdf|doc|xls|ppt|txt|odt|ods|odp|odf|tar|bmp|rtf|js|mp3|avi|mpeg|flv|html|htm)$ {
proxy_cache off;
root /home/admin/web/kino24-7.ru/public_html;
access_log /var/log/httpd/domains/kino24-7.ru.log combined;
access_log /var/log/httpd/domains/kino24-7.ru.bytes bytes;
expires max;
try_files $uri @fallback;
}
}
 
Назад
Сверху