Для нормальной работы сайта необходимо разрешить JavaScript, включая скрипты с доменов googlesyndication.com и doubleclick.net для отображения системы поиска по сайту и прочих сервисов Google.

Тотальное кэширование бэкенда на APACHE + PHP 5.3 aka FCGI в фронтэнде NGINX

Тотальное кэширование бэкенда на APACHE + PHP 5.3 aka FCGI в фронтэнде NGINX Кэширование в NGINX для анонимных и зарегистрированных пользователей. Кэширование контента в фронтэнде NGINX помогает существенно снизить нагрузку на бэкенд, а соответственно и на весь сервер в целом...

Превед, люби друзи:) Сегодня вашему вниманию представляется очередной, НЕ тупая копи/паста, шедевр. Итак..., в этом посте не будет идти речь про установку APACHE + PHP 5.3 aka FCGI и подразумевается, что APACHE + PHP 5.3 aka FCGI уже установлен, настроен и теперь мы хотим замутить тотальное кэширование контента в фронтэнде NGINX для анонимных и не кэшировать его для зарегистрированных пользователей, для зарегистрированных пользователей будет достаточно внутреннего кэша самой CMS и внутренних акселераторов типа eAccelerator или APC имхо еже зарегистрированные пользователи должны получать как можно более актуальное содержимое сайта!

ВЫНИМАНИЕ!:) Кэширование в nginx настраивается отдельно для каждого из модулей fastcgi и proxy, ниже мы рассматриваем настройку для модуля proxy, а чтобы всё это работало и для fastcgi, то нужно везде изменить proxy_cache* на fastcgi_cache* соответственно!

Мана по настройке кэширования в NGINX в сети валом, вот например "Куроводство | Наблы | 56. Подводные камни при использовании кэширования в nginx", по которым можно настроить кэширование в NGINX, но не факт, что оно будет работать должным образом. Разбор полётов начнём с проблем...

NGINX не кэширует

Стою на асхвальте у лыжи обутый:)...


Так например в посте по упомянутой выше ссылке, да и не только в нём, рекомендуется использовать директиву proxy_cache_key следующим диким образом:

proxy_cache_key "$request_method|$http_if_modified_since|$http_if_none_match \
    |$host|$request_uri";

При этом приводится мутная, не до конца ясная и полная, аргументация необходимости использования, иногда встречается бред такого вида:

proxy_cache_key "$is_args|$request_method|$http_if_modified_since \
    |$http_if_none_match|$host|$request_uri";

При такой конфигурации значений в proxy_cache_key, nginx не будет кэшировать контент, вернее кэшировать будет ибо каталог с кэшем постоянно будет наполнятся, а эффекта от этого будет ноль!;( Как понять что нет эффекта от кэширования? Да очень просто, например повесить на сайт динамический модуль (к примеру модуль ротации баннеров) с обновлением раз в 15 минут при этом время жизни кэша в nginx установить равным в 1h, т.е. в 1 час и понаблюдать меняются ли баннеры или ещё проще, создать временный ХТМЛ файл и однократно обратится к нему через браузер, потом удалить его с сервера и обратиться повторно к уже не существующему файлу.

Бредовость выше описанной комбинации значений proxy_cache_key упоминалась здесь >>> Согласно оф. документации значение директивы proxy_cache_key близко к такой строке $scheme$proxy_host$uri$is_args$args. Список и описание переменных NGINX мы найдём тут >>>

Самым лучшим вариантом будет вовсе не определять proxy_cache_key! NGINX сам знает, что ему кэшировать, а если сильно хочется определить proxy_cache_key, то на худой конец можно попробовать использовать такую комбинацию:

proxy_cache_key "$scheme$proxy_host$uri$is_args$args|$scheme$host$request_uri";

Повторюсь - наличие файлов в директории /var/cache/nginx/pagecache, размер которой можно проверить командой du -shc /var/cache/nginx/pagecache/, не говорит о том, что клиенту в браузер отдаётся реально кэшированный контент!

Кэширование может не работать из-за proxy_buffering off отключенной буферизации ответов проксируемого сервера. Указываем явно proxy_buffering on, а также игнорируем заголовок "X-Accel-Buffering" через значение которого в off буферизация ответов проксируемого сервера может быть отключена.

Так в proxy_ignore_headers должны быть проигнорированы следующие заголовки: "Set-Cookie" "Cache-Control" "Expires" "X-Accel-Buffering", а иначе лыжи не поедут - т.е. кэш будет расти, а контент всё равно будет браться с "бакэнда"!!! Ещё важно добавить страницу авторизации в исключения кэширования директивой proxy_cache_bypass /URL /OTHER_URL иначе кукиши будут проигнорированы директивой proxy_ignore_headers и не смогут быть установлены!.

Обойти УРЛ с параметрами через proxy_cache_bypass и proxy_no_cache не удалось, хоть и в официальной  документации сказано что эти директивы принимают строку, а какую строку? - догадайся сам! Пришлось в ссылку для авторизации добавить аргумент &nocache=true, его же прописать в шаблонах форм авторизации (guests.denied.php, frontpage.guests.php, mobile.login.php, block.unregistered.php, mod_login) и обходить кэширование страниц авторизации через "proxy_cache_bypass $arg_nocache;" и "proxy_no_cache $arg_nocache;" соответственно - хотя товарищ Сысоев на своём форуме и заявлял, что мол POST запросы не кэшируются, но видимо всё вплоть до наоборот..., раз приходится обходить кэширование POST форм (вернее УРЛ-ов) авторизации, а иначе авторизации.нет;((.

Если учесть упомянутые выше нюансы, то кэширование в NGINX работает замечательно без необходимости дополнительных телодвижений. В редких случаях возможно будет полезным очистка заголовков If-Modified-Since и If-None-Match:

proxy_set_header  If-Modified-Since  "";
proxy_set_header  If-None-Match      "";

Ещё иногда NGINX не кэширует когда присутствует файл /etc/nginx/conf.d/default.conf - переименуйте его mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak.

Кэширование в NGINX для анонимных и зарегистрированных пользователей

Для кэширования в NGINX для анонимных и зарегистрированных пользователей можно использовать несколько вариантов с проверкой наличия кукишей с определённым именем:

proxy_no_cache $cookie_name;
proxy_cache_bypass $cookie_name;

В примере выше контент не будет кэширован proxy_no_cache и не будет браться из кэша proxy_cache_bypass если установлен кукиш с именем "name". Ещё один извратный вариант кэширования в NGINX только для анонимных:

if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_" )
{
    set $nocache 1;
}
proxy_no_cache $nocache;
proxy_cache_bypass $nocache;

Можно также отключать кэширование при наличии определённых HTTP заголовков или аргументов (строки запроса), дополнительно гульчитаем в документации

После редактирования vi /etc/nginx/nginx.conf, сохраняем его и перезапускаем сервер service nginx restart, а также можем протестировать новую конфигурацию ab -n 1000 -c 100 http://www.mysite.com/

И под занавес немного о параметре keys_zone=pagecache:15m... Как правильно рассчитать keys_zone? На некоторых сайтах часто встречается не верное трактование сего параметра, а именно говорится о том, что в keys_zone указывается размер кэша который хранится на диске - это ошибка! В keys_zone определяется размер разделяемой оперативной памяти для более оперативной обработки поступающих запросов, а размер дискового кэша определяется в max_size=500m.

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

{pub}

 

{/pub} {reg}

user  nginx;
worker_processes  5;
worker_rlimit_nofile 100000;
timer_resolution 100ms;
 
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
 
 
events {
    # max connections for each process
    worker_connections  1024;
}
 
 
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    client_max_body_size 100m;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" "$gzip_ratio"';
 
    access_log  /var/log/nginx/access.log  main;
 
    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;
    server_tokens   off;
    gzip            on;
    gzip_static     on;
    gzip_comp_level 5;
    gzip_proxied     any;
    gzip_min_length 200;
    keepalive_timeout  5;
    reset_timedout_connection on;
    limit_conn_zone   $binary_remote_addr  zone=addr:10m;
    gzip_types text/plain text/xml application/xml application/x-javascript text \
/javascript text/css text/json application/json;
 
    # PROXY MODULE SETTINGS...
    # enable proxy buffering
    proxy_buffering on;
    # http://nginx.org/ru/docs/http/ngx_http_proxy_module.html
    proxy_hide_header "X-Powered-By";
    proxy_cache_path /var/cache/nginx/pagecache levels=1:2 keys_zone=pagecache:1 \
5m inactive=60m max_size=500m;
    proxy_cache_use_stale error timeout invalid_header updating http_404 http_50 \
0 http_502 http_503 http_504;
 
    # Load config files from the /etc/nginx/conf.d directory
    include /etc/nginx/conf.d/*.conf;
 
    server {
        # http://nginx.org/ru/docs/http/ngx_http_core_module.html
        listen      *:80;
        server_name remoteshaman.com www.remoteshaman.com;
 
        error_log  /var/www/wrs/logs/nginx_error.log warn;
        access_log /var/www/wrs/logs/nginx_access.log;
 
        # http://nginx.org/ru/docs/http/ngx_http_limit_conn_module.html
        limit_conn addr 30;
 
        # Must by off if isset apache httpd redirect in .htaccess
        proxy_redirect off;
 
        fastcgi_buffer_size 16k;
        fastcgi_buffers 64 16k;
 
        proxy_buffer_size 16k;
        proxy_buffers 64 16k;
 
 
        # Default zone
        error_page 404 = @nocached;
 
        # NO cache for user
        location @nocached {
            proxy_pass       http://localhost:81;
            proxy_cache    off;
            proxy_set_header Host      $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $http_x_forwarded_for;
        }
 
        # Cache for guest
        location @cached {
            proxy_pass       http://localhost:81;
            proxy_set_header Host      $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $http_x_forwarded_for;
 
            # activate cache in 'zonename' (proxy_cache_path) or 'off'
            proxy_cache    pagecache;
            proxy_cache_valid 200 304 3h;
            proxy_hide_header "Set-Cookie";
            proxy_no_cache $arg_nocache;
            proxy_cache_bypass $arg_nocache;
            proxy_ignore_headers "Set-Cookie" "Cache-Control" "Expires" "X-Accel-Buffering";
        }
 
        # Set 404 for all request
        location = / {
 
            error_log /dev/null crit;
            access_log  off;
 
            return 404;
        }
 
        location / {
 
            error_log /dev/null crit;
            access_log  off;
 
            # if not cookie name
            if ($http_cookie !~ "userid" ) {
                set $cached 1;
            }
 
            if ($request_method = POST) {
                set $cached 0;
            }
 
            if ($request_method != GET) {
                set $cached 0;
            }
 
            if ($cached = 1) {
                error_page 404 405 502 504 = @cached;
                break;
            }
 
            if ($cached = 0) {
                error_page 404 405 502 504 = @nocached;
                break;
            }
 
        }
 
        location /administrator/cache/        { deny all; }
        location /administrator/language/     { deny all; }
        location /cache/                      { deny all; }
        location /language/                   { deny all; }
        location /logs/                       { deny all; }
        location /tmp/                        { deny all; }
 
        location ~* \.(jpg|jpeg|gif|png|ico|css|bmp|swf|js|mp3|zip|gz|tgz)$
        {
            expires      1d;
            add_header  Cache-Control  public;
            proxy_pass       http://localhost:81;
            proxy_set_header Host      $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $http_x_forwarded_for;
            access_log  off;
        }
 
 
        #error_page  404              /404.html;
 
        #location = /404.html {
        #   root   /usr/share/nginx/html;
        #}
 
        # redirect server error pages to the static page /50x.html
        #
        #error_page   500 502 503 504  /50x.html;
        #location = /50x.html {
        #   root   /usr/share/nginx/html;
        #}
 
        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #   proxy_pass   http://127.0.0.1;
        #}
 
        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #   root           html;
        #   fastcgi_pass   127.0.0.1:9000;
        #   fastcgi_index  index.php;
        #   fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #   include        fastcgi_params;
        #}
 
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #   deny  all;
        #}
    }
}

{/reg}

Если в Apache .htaccess используется склейка доменов по редиректу 301, то директива proxy_redirect off; должна обязательно присутствовать в /etc/nginx/nginx.conf иначе когда чел обратится по адресу http://www.mysite.com/, а редирект его перекинет на http://mysite.com/, т.е. уже без www., то ответ 301 Moved Permanently будет закэширован и будет отображаться вместо главной страницы на протяжении времени валидности кэша!:)

Ссылки по теме

Олег Головский

Рекомендуемый контент



Добавить комментарий


Защитный код
Обновить

Рейтинг@Mail.ru 4 megabytes