Кешування відповіді від backend за допомогою NGINX

NGINX дає змогу значно прискорити процес завантаження сторінки, не звертаючись до бекенда, а видаючи готовий html із кешу. Для роботи цієї функції необхідно, щоб веб-сервер був версії 0.7.44 і вище (перевірити можна командою nginx -v).

Для FastCGI кеш задається за допомогою опцій fastcgi_cache_. Для запитів до бекенда за допомогою proxy_pass — proxy_cache_.

Рекомендації та протипоказання

Кеш — це дані не першої свіжості. Це важливо враховувати, якщо ми хочемо налаштувати ефективне кешування засобами nginx. Ми можемо зіткнутися з різними проблемами, наприклад, нездатність сервера продовжити сесію авторизованого користувача або відображення старої інформації на порталі з динамічно мінливим контентом. Щоб уникнути цих проблем, налаштування nginx має бути тісно пов'язане з розробкою сайту. Ідеальна робота кешу можлива тільки за умови повного розуміння внутрішніх механізмів роботи порталу, як-от надсилання запитів на авторизацію, подовження сесії, оновлення контенту — програміст може написати для цього запит за певними URL, для якого адміністратор NGINX може відключити кешування.

Кешування динаміки буде корисним для сайтів з високою відвідуваністю, через яку створюється високе навантаження на сервер і він не може встигнути виконати обробку запитів. Також воно буде корисним для окремих сторінок, вміст яких змінюється дуже рідко, але відпрацювання скриптів виконується довго.

З усього цього можна зробити висновок, що кешування на стороні сервера NGINX варто застосовувати тільки в разі високих навантажень і повільної роботи сайту через довгу роботу backend'а.

Налаштування кешування для proxy_pass

Як було сказано вище, для різних методів звернення до сервера, який обробляє запит, потрібно використовувати різні методи кешування.

Увімкнення кешування

Відкриваємо конфігураційний файл nginx:

vi /etc/nginx/nginx.conf

У секцію http додаємо:

http {
    ...
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=all:64m inactive=2h max_size=2g;
    ...
}

У цьому прикладі ми задали глобальне налаштування для кешування:

  • /var/cache/nginx — шлях зберігання кешу.
  • levels — рівень вкладеності каталогів. У цьому прикладі ми задаємо налаштування, за якого в каталог із кешем буде створено каталог, а в ньому — ще один каталог.
  • keys_zone — ім'я зони в поділюваній пам'яті, де зберігатиметься кеш, а також її розмір.
  • inactive — задає час, після якого кеш буде автоматично чиститися.
  • max_size — максимальний розмір даних під кеш. Коли місце закінчується, nginx сам видаляє застарілі дані.

Створюємо каталог для зберігання кешу і задаємо власника:

mkdir /var/cache/nginx
chown nginx:nginx /var/cache/nginx

Налаштування хостів

Щоб певний сайт або окрема сторінка кешувала запит, відкриваємо конфігураційний файл із налаштуваннями віртуального домену або хоста, наприклад:

vi /etc/nginx/conf.d/default.conf

… і додамо до proxy_pass кешування — ми отримаємо щось на кшталт:

 location / {
        if ($http_cookie ~* ".+" ) {
            set $cookie_cache_bypass 1;
        }
        proxy_cache_bypass $cookie_cache_bypass;
        proxy_pass http://localhost:3000;
        ...
        proxy_cache all;
        proxy_cache_methods GET POST HEAD;
        proxy_cache_valid 404 502 503 5m;
        proxy_cache_valid any 1h;
        proxy_cache_use_stale error timeout invalid_header updating;
    }

де:

  • set $cookie_cache_bypass 1 — задаємо значення змінної $cookie_cache_bypass, якщо передаються куки. Необхідно для запобігання віддачі застарілих даних.
  • proxy_cache_bypass — не віддавати дані з кешу. У нашому випадку, застосовується при куках.
  • proxy_pass — передає запити на бекенд.
  • proxy_cache_methods — за замовчуванням, закешованими будуть тільки запити GET і HEAD. Якщо нам потрібні інші методи, то додаємо їх. У нашому прикладі додано POST.
  • proxy_cache — вмикаємо кешування.
  • proxy_cache_valid — задає час кешування. У нашому прикладі перший параметр задає кешування сторінок із кодами відповідей 404, 502, 503 на 5 хвилин, другий — для всього іншого на 1 годину.
  • proxy_cache_use_stale — вказує, в яких випадках можна віддати застарілий кеш.

Застосування налаштувань

NGINX налаштований. Перевіримо коректність налаштувань і застосовуємо їх, якщо немає помилок:

nginx -t && nginx -s reload

Тепер заходимо на сайт і дивимося в каталог із кешем — у ньому мають з'явитися каталоги і файли:

Мы должны увидеть что-то на подобие:

drwx------. 3 nginx nginx 4096 Jan 25 16:09 0
drwx------. 5 nginx nginx 4096 Jan 25 16:09 2
drwx------. 5 nginx nginx 4096 Jan 25 16:15 3
drwx------. 3 nginx nginx 4096 Jan 25 16:09 4
drwx------. 4 nginx nginx 4096 Jan 26 05:08 5
drwx------. 3 nginx nginx 4096 Jan 25 16:09 6
drwx------. 3 nginx nginx 4096 Jan 26 04:18 7
drwx------. 3 nginx nginx 4096 Jan 25 16:10 8
drwx------. 5 nginx nginx 4096 Jan 25 16:15 a
drwx------. 3 nginx nginx 4096 Jan 25 16:09 b
drwx------. 5 nginx nginx 4096 Jan 26 04:19 e
drwx------. 3 nginx nginx 4096 Jan 25 19:55 f

Налаштування кешування для fastcgi_pass

Налаштування fastcgi_cache аналогічне proxy_cache і налаштування можна зробити за подобою останнього, замінивши proxy_ на fastcgi_. Ми розберемо основні налаштування без подробиць і коментарів.

Відкриваємо конфіг nginx:

vi /etc/nginx/nginx.conf

Додаємо в секцію http:

http {
    ...
    fastcgi_cache_path /var/cache/fastcgi levels=1:2 keys_zone=fastcgi:64m inactive=2h max_size=2g;
    ...
}

зверніть увагу, що в цьому прикладі інший каталог і keys_zone.

Створюємо каталог для кешу:

mkdir /var/cache/fastcgi
chown nginx:nginx /var/cache/fastcgi

Налаштовуємо хост:

vi /etc/nginx/conf.d/default.conf
location / {
        if ($http_cookie ~* ".+" ) {
            set $cookie_cache_bypass 1;
        }
        fastcgi_cache_bypass $cookie_cache_bypass;
        fastcgi_pass http://localhost:9000;
        ...
        fastcgi_cache all;
        fastcgi_cache_methods GET POST HEAD;
        fastcgi_cache_valid 404 502 503 5m;
        fastcgi_cache_valid any 1h;
        fastcgi_cache_use_stale error timeout invalid_header updating;
    }

опції fastcgi_ аналогічні опціям proxy_.

Перевіряємо налаштування і застосовуємо їх:

nginx -t && nginx -s reload

Кешування статики

Кешування статики не має жодного стосунку до кешування відповіді від бекенда, однак, це теж дає змогу розвантажити сервер. Суть у тому, що nginx сам вміє віддавати статичні файли + задавати інструкцію для браузера щодо її кешування.

Налаштування виконується для кожного віртуального хоста (секція server):

server {
        ...
        location ~* ^.+\.(css|js)$ {
            root /var/www/site
            expires modified +1w;
        }
        location ~* ^.+\.(jpg|jpeg|gif|png)$ {
            root /var/www/site
            expires max;
        }
    }

У цьому прикладі ми задаємо для файлів зображень (jpg, jpeg, gif, png) кеш до 31 грудня 2037 року 23:55:55 (max), для файлів css і js — 1 тиждень з моменту їхньої модифікації. Ці налаштування ми задаємо за допомогою параметра expires, який, своєю чергою, задає заголовок cache-control. NGINX шукатиме статичні файли в кореневому каталозі /var/www/site.

Після застосовуємо налаштування:

systemctl restart nginx

Вимкнення кешування

Як йшлося вище, у деяких випадках кешування може нашкодити і на деяких сторінках його варто відключити. У налаштуваннях віртуального хоста ми можемо створити окремий location, для якого відключитися кеш, наприклад:

    location /proxy_nocache {
        proxy_pass http://localhost:3000;
        ...
        proxy_cache off;
    }
    location /fastcgi_nocache {
        fastcgi_pass http://localhost:9000;
        ...
        fastcgi_cache off;
    }

Зверніть увагу, що в цьому прикладі ми відключаємо кешування як для запитів proxy_pass, так і fastcgi_pass.

При відключенні кешування для статики використовуємо таку конфігурацію:

 server {
        ...
        location ~* ^.+\.(jpg|jpeg|gif|png|css|js)$ {
            root /var/www/site
            expires epoch;
        }
    }

expires epoch встановить заголовок сache-control з часом закінчення кешу «1 січня 1970 00:00:01».

Скидання кешу

Видалити кеш на стороні сервера nginx ми можемо тільки для бекенда. Для статики потрібно видаляти кеш у самому браузері (наприклад, у налаштуваннях або за допомогою доповнень).

Для скидання кешу ми просто маємо видалити вміст каталогу, який прописано в опції proxy_cache_path або fastcgi_cache_path — у нашому випадку, це /var/cache/nginx і /var/cache/fastcgi відповідно.

а) для proxy_cache_path:

rm -r /var/cache/nginx/*

б) для fastcgi_cache_path:

rm -r /var/cache/fastcgi/*

Зберігання кешу в оперативній пам'яті

Ми можемо значно прискорити процес запису і читання інформації, якщо зберігатимемо кеш в оперативній пам'яті.

Створюємо звичайний каталог, у який монтуватимемо частину оперативної пам'яті надамо на нього повні права:

mkdir /var/ramdisk
chmod 777 /var/ramdisk

Монтуємо частину оперативної пам'яті як звичайний каталог:

mount -t tmpfs -o size=2G ramdisk /var/ramdisk

У цьому прикладі ми монтуємо 2 Гб оперативної пам'яті як папку /var/ramdisk. Можливо, правильніше буде заздалегідь переконатися в наявності вільної пам'яті командою free.

Для автоматичного монтування відкриваємо на редагування fstab:

vi /etc/fstab

… і додаємо:

ramdisk       /var/ramdisk tmpfs   nodev,nosuid,noexec,nodiratime,size=2G   0 0

Тепер, коли у нас є каталог, дані якого зберігаються в оперативній пам'яті, редагуємо параметр proxy_cache_path або fastcgi_cache_path у NGINX:

vi /etc/nginx/nginx.conf
proxy_cache_path /var/ramdisk levels=1:2 keys_zone=all:64m inactive=2h max_size=2g;

або

fastcgi_cache_path /var/ramdisk levels=1:2 keys_zone=fastcgi:64m inactive=2h max_size=2g;

Перезапускаємо nginx:

systemctl restart nginx