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

Тема в разделе "Администрирование серверов", создана пользователем porsche2, 20 апр 2012.

Модераторы: mefish, stooper
  1. porsche2

    porsche2

    Регистр.:
    18 ноя 2007
    Сообщения:
    667
    Симпатии:
    210
    Файловое кеширование 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();
     
    // конец файового кэширование страниц






    2. Жмем то, что еще не сжато и выравниваем время
    compress.sh

    Код:
    #! /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

    Код:
    #! /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. Ругайтесь тише
     
  2. Александр Остроушко

    Александр Остроушко Писатель

    Регистр.:
    13 июл 2016
    Сообщения:
    4
    Симпатии:
    0
    Добрый день. Следовал инструкциям из Вашей темы Файловое кеширование 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
    В чем может быть проблема?
    Спасибо
     
  3. Kub

    Kub

    Регистр.:
    5 июн 2009
    Сообщения:
    623
    Симпатии:
    483
    Наверно нет модуля ngx_http_perl_module
    Перейти по ссылке

    Для проверки что включено в nginx и версию
    Код:
    nginx -V
    Затем проверяете есть perl_module
     
  4. Александр Остроушко

    Александр Остроушко Писатель

    Регистр.:
    13 июл 2016
    Сообщения:
    4
    Симпатии:
    0
    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 ~]#
    Получается нет, буду читать как установить. Спасибо, если что можно еще обращаться?
     
  5. Александр Остроушко

    Александр Остроушко Писатель

    Регистр.:
    13 июл 2016
    Сообщения:
    4
    Симпатии:
    0
    А не подскажите как его подключит. По всей видимости установлен, а как подключит, облазил в интернете не нашел, точнее не понял. Вот что есть его сборку необходимо разрешить с помощью конфигурационного параметра --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.
     
  6. Kub

    Kub

    Регистр.:
    5 июн 2009
    Сообщения:
    623
    Симпатии:
    483
    Нужно собрать из исходников и при компиляции указать параметр --with-http_perl_module
    Примерно по этому руководству нужно делать Перейти по ссылке
    Скачивать нужно последнюю стабильную версию Перейти по ссылке
    Только скрипт инициализации нужно будет добавить как в руководстве написано.

    Или лучше не удалять уже установленный 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 
     
    Последнее редактирование: 4 фев 2017
  7. Александр Остроушко

    Александр Остроушко Писатель

    Регистр.:
    13 июл 2016
    Сообщения:
    4
    Симпатии:
    0
    Добрый вечер. С горем пополам удалось подключить 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;
    }
    }