в nginx

Настройка кэширования на Nginx

nginx
Суть кеширования на стороне сервера заключается в том, чтобы избавиться от постоянного запуска одних и те же скриптов (как пример, генерации ленты постов WordPress), выполнение которых может иногда занимать целые секунды.

С использованием кэширования приложение сгенерирует страницу один раз и сохранит результат в память на какое-то время (называемое TTL). Пока не истечет TTL, клиент будет получать сохраненную в памяти версию страницы. Давайте разберемся с настройкой кэширования на Nginx!

Преимущества кэширования Nginx по сравнению с Varnish состоят прежде всего в простоте настройки. Оптимально использовать кэширование для сайтов с контентом, который доступен неавторизованным пользователям (публичный).

Считаем, что Nginx у нас установлен из пакетов (или собран из исходников) и настроен.

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

...
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=all:32m;
...

Не забываем создать каталог для кеширования, который мы указали выше:

mkdir /var/cache/nginx

Далее следует изменить настройки сайта, создав еще одну секцию server. Переносим наш основной сервер на другой порт (например, 81), а на стандартном 80 у нас теперь будет работать кэширующий хост, который либо будет отдавать данные из кэша, либо перенаправлять запросы на основной хост. Это может выглядеть примерно так:

server {
    listen 80;

    location / {
        proxy_pass http://127.0.0.1:81/;
        proxy_cache all;
        proxy_cache_valid any 1h; # Кешируем на 1 час 

}

Для основного сервера:

server {
    listen 81;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    access_log /var/log/nginx/letsclearitup.access.log;
    error_log  /var/log/nginx/letsclearitup.error.log error;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/letsclearitup.sock;
        fastcgi_hide_header X-Powered-By;
    }

    location /status {
        fastcgi_pass unix:/run/php/letsclearitup.sock;
        include fastcgi.conf;
        allow 127.0.0.1;
        deny all;
    }
}

Если у пользователя установлены какие-либо Cookies, кэширование можно отключить:

server {
    listen 80;

    location / {
        if ($http_cookie ~* ".+" ) {
            set $do_not_cache 1;
        }
        proxy_pass http://127.0.0.1:81/;
        proxy_cache all;
        proxy_cache_valid any 1h; # Кешируем на 1 час 
    }
}

Есть смысл включать кэширование также и для ошибочных запросов, чтобы снизить нагрузку от обращений к неработающей части сайта:

server {
    listen 80;

    location / {
        if ($http_cookie ~* ".+" ) {
            set $do_not_cache 1;
        }
        proxy_pass http://127.0.0.1:81/;
        proxy_cache all;
        proxy_cache_valid 404 502 503 1m;
        proxy_cache_valid any 1h; # Кешируем на 1 час 
    }
}

У Nginx есть возможность кеширования ответов от fastcgi. Чтобы использовать данную возможность, в секции http файла /etc/nginx/nginx.conf добавляем:

...
fastcgi_cache_path /var/cache/fpm levels=1:2 keys_zone=fcgi:100m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
...

Создаем каталог:

mkdir /var/cache/fpm

После чего в настройках сайта (в секции server для основного хоста) добавим такие строки:

server {
    listen 81;
...
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/letsclearitup.sock;
        fastcgi_hide_header X-Powered-By;
        fastcgi_cache fcgi;
        fastcgi_cache_valid 200 60m; # кешировать ответы с кодом 200 на 1 час 
    }
...
}

Настройка кэширования на Nginx довольно проста, но если все сделать правильно, то можно получить десятикратное ускорение сайта и неплохую экономию ресурсов.

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

11 Комментария

  1. Подскажите , имею вот такие конфиги, что ещё нужно в них добавить? Когда на сайте что-то меняю или пишу пост, загружаю картинку, контент не появляется сразу, а только после обновления страницы. Сайт вордпресс.

    user www-data;
    worker_processes 1;

    error_log /var/log/nginx/error.log warn;
    pid /var/run/nginx.pid;

    events {
    worker_connections 1024;
    }

    http {
    gzip on;
    gzip_disable «msie6»;
    gzip_comp_level 6;
    gzip_min_length 1100;
    gzip_buffers 16 8k;
    gzip_proxied any;
    gzip_types
    text/plain
    text/css
    text/js
    text/xml
    text/javascript
    application/javascript
    application/x-javascript
    application/json
    application/xml
    application/xml+rss;
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main ‘$remote_addr — $remote_user [$time_local] «$request» ‘
    ‘$status $body_bytes_sent «$http_referer» ‘
    ‘»$http_user_agent» «$http_x_forwarded_for»‘;

    access_log /var/log/nginx/access.log main;
    server_tokens off;

    sendfile on;
    #tcp_nopush on;

    keepalive_timeout 65;

    #gzip on;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/vhosts/*/*.conf;
    client_max_body_size 128m;
    server {
    server_name localhost;
    disable_symlinks if_not_owner;
    include /etc/nginx/vhosts-includes/*.conf;
    location @fallback {
    error_log /dev/null crit;
    proxy_pass http://127.0.0.1:8080;
    proxy_redirect http://127.0.0.1:8080 /;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    access_log off ;
    }
    listen 80;
    listen [::]:80;
    }
    }

    и хоста
    fastcgi_cache_path /var/tmp/nginx/sait.ru levels=2 keys_zone=pitcha:16m max_size=512m inactive=1d;
    server {
    server_name sait.ru http://www.sait.ru;
    charset UTF-8;
    index index.php;
    disable_symlinks if_not_owner from=$root_path;
    include /etc/nginx/vhosts-includes/*.conf;
    include /etc/nginx/vhosts-resources/sait.ru/*.conf;
    access_log /var/www/httpd-logs/sait.ru.access.log;
    error_log /var/www/httpd-logs/sait.ru.error.log notice;
    ssi on;
    set $root_path /var/www/www-root/data/www/sait.ru;
    root $root_path;
    expires 7d;
    listen ip adress:80;
    listen [ip adress:118]:80;
    location / {
    try_files $uri $uri/ /index.php?$args;
    location ~ [^/]\.ph(p\d*|tml)$ {
    try_files /does_not_exists @php;
    }
    }
    location @php {
    fastcgi_index index.php;
    fastcgi_param PHP_ADMIN_VALUE «sendmail_path = /usr/sbin/sendmail -t -i -f support@sait.ru«;
    fastcgi_pass unix:/var/www/php-fpm/www-root.sock;
    fastcgi_split_path_info ^((?U).+\.ph(?:p\d*|tml))(/?.+)$;
    try_files $uri =404;
    include fastcgi_params;
    }
    }
    server {
    server_name sait.ru http://www.sait.ru;
    ssl on;
    ssl_certificate «/var/www/httpd-cert/www-root/sait.ru_le1.crtca»;
    ssl_certificate_key «/var/www/httpd-cert/www-root/sait.ru_le1.key»;
    ssl_ciphers EECDH:+AES256:-3DES:RSA+AES:!NULL:!RC4;
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_dhparam /etc/ssl/certs/dhparam4096.pem;
    charset UTF-8;
    index index.php;
    disable_symlinks if_not_owner from=$root_path;
    include /etc/nginx/vhosts-includes/*.conf;
    include /etc/nginx/vhosts-resources/sait.ru/*.conf;
    access_log /var/www/httpd-logs/sait.ru.access.log;
    error_log /var/www/httpd-logs/sait.ru.error.log notice;
    ssi on;
    set $root_path /var/www/www-root/data/www/sait.ru;
    root $root_path;
    expires 7d;
    listen [ip adress:118]:443;
    listen ip adress:443;
    location / {
    try_files $uri $uri/ /index.php?$args;
    location ~ [^/]\.ph(p\d*|tml)$ {
    try_files /does_not_exists @php;
    }
    }
    location @php {
    fastcgi_index index.php;
    fastcgi_param PHP_ADMIN_VALUE «sendmail_path = /usr/sbin/sendmail -t -i -f support@sait.ru«;
    fastcgi_pass unix:/var/www/php-fpm/www-root.sock;
    fastcgi_split_path_info ^((?U).+\.ph(?:p\d*|tml))(/?.+)$;
    try_files $uri =404;
    include fastcgi_params;
    }
    }

    • «Подскажите , имею вот такие конфиги, что ещё нужно в них добавить? Когда на сайте что-то меняю или пишу пост, загружаю картинку, контент не появляется сразу, а только после обновления страницы. Сайт вордпресс.»

      А в чем собственно вопрос? Так и должно быть, изменений без обновления страницы вы не увидите.
      Более того, если у вас на главной список постов, то при публикации новой записи вы ее не увидите на главной даже обновляя страницу — пока не почистите кеш…

      • При открытия сайта, открывается копия без изменений, При обновлении страницы, они появляются. Но например если я закрою браузер, а потом открою, откроется страницы без изменений, а при обновлении страницы они появятся.
        У меня в конфигах нет пунктов fastcgi_cache_path и proxy_cache_path я так понял?
        я скачал плагин — Nginx Cache, который обновляет кэш при внесении изменений. Там есть поле адрес кэша, я вписал из конфига — /var/tmp/nginx/sait.ru . Но показывает Filesystem API could not be initialized.

        • Более того, если у вас на главной список постов, то при публикации новой записи вы ее не увидите на главной даже обновляя страницу — пока не почистите кеш…

          И что это значит? Каждый раз чистить кэш после публикации? А если добавлять посты будут другие люди?

          • Да, в предложенном мной варианте настройки нужно после каждой публикации чистить кеш — любым удобным для вас способом (curl / postman / из консоли и т.д.).
            Если посты будут добавлять другие люди, то такой вариант вам не подойдет — нужно будет либо давать этим людям доступ на очистку кеша, либо пробовать какие-то плагины (что вы и пытаетесь делать), либо вообще убрать этот вариант кеширования

        • Дмитрий, я понятия не имею как работает скачанный вами плагин, что он должен делать (и что он делает на самом деле) — спросите у его разработчиков. Статья о настройке кеширования на чистом nginx, ни о каких плагинах речь в ней не идет.

    • Да тут, собственно, никаких сложностей и нет, вроде.
      Сертификат на NGINX-хосте, закрываем на нём сессию, с бекендами общаемся по HTTP, если позволяет сеть, если нет — на бекенде поднимаем второй SSL.
      Бекенд в upstream, с портом, потом через proxy_pass в Location — браузер этого не отображает никак и все хорошо…

      Можете еще дополнительно посмотреть fastcgi-кеширование…