====== Прозрачное кэширование в nginx, для всех и каждого ======
Источник - http://sanmai.livejournal.com/1013539.html
Представим, что у нас есть сайт, на который регулярно даёт ссылки [[http://navalny.livejournal.com/|navalny]].\\
Нам нужно защитить его от всплесков посещаемости. Как это сделать?
С версии 0.8.46 в nginx появились опции, позволяющие легко и просто настроить прозрачное кэширование для анонимных пользователей.
Для работы этой схемы от сайта требуется очень мало: достаточно лишь не начинать сессию, то есть не отправлять сессионную куку, без явной на то необходимости. Редкий сайт нельзя довести до такого состояния, а значит большинство сайтов можно защитить от резких всплесков посещаемости с помощью nginx с минимальными затратами сил и времени.
===== Научим сайт начинать сессию только когда она нужна =====
Для обычных сайтов на PHP это можно сделать выставив в ноль session.auto_start в php.ini или, лучше, в настройках виртуального хоста Apache. Также нам нужно задать подходящие имя для сессионной куки:
php_admin_value session.name "session"
php_admin_value session.auto_start 0
Если сайт сам стартует сессию в коде, то **session_start()** следует заменить на:
if (!empty($_COOKIE[session_name()]) || $_SERVER['REQUEST_METHOD'] == 'POST') {
session_id() || session_start();
}
Так, сессия будет начата только если
* куки с сессией уже есть или если
* нам отправляют форму, например, с логином и паролем.
Что нам и требовалось.
===== Настроим nginx на кэширование запросов без сессионной куки =====
После того как мы добились того, что сайт не отправляет сессионную куку гостям сайта, настроим nginx на сохранение в кэш запросов без сессионной куки.
В любом удобном месте, например, в конфиге виртуального хоста nginx перед блоком server, добавим строки:
proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=cache:30m max_size=1G;
proxy_temp_path /var/lib/nginx/proxy 1 2;
proxy_ignore_headers Expires Cache-Control;
proxy_cache_use_stale error timeout invalid_header http_502;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
Не забываем создать соответствующие каталоги:
mkdir -p /var/lib/nginx/cache
chown -R www-data /var/lib/nginx/cache
chmod 700 /var/lib/nginx/cache
В соответствующий блок location добавим следующие строки:
location / {
proxy_cache cache;
proxy_cache_valid 10m;
proxy_cache_valid 404 1m;
proxy_pass http://apache-backend;
}
Перезапускаем nginx, удаляем куки из браузера и наслаждаемся скоростью работы сайта.
===== Тонкая настройка кэширования =====
Если вы хотите чтобы кэшировались только некоторые страницы, или, например, чтобы некоторые адреса кэшировались на время большее 10 минут, для явного задания времени кэширования используйте:
header("X-Accel-Expires: $seconds");
Для полного отключения кэширования, например, счетчиков, используйте:
header("X-Accel-Expires: 0");
===== Проверка на прочность =====
Проверим главную страницу сайта на прочность в сто потоков:
ab -n 1000 -c 100 http://www.example.com/
C использованием кэширования тестовый сайт легко выдавал более 100 rps, оно и понятно.
Без использования - предсказуемо показывал 503 ошибку на ~70% запросов.
===== Принудительное обновление кэша =====
Если в директиву **proxy_cache_bypass** изменить так:
proxy_cache_bypass $cookie_session $http_x_update;
То можно будет принудительно обновлять кэш страницы при необходимости запросом со заголовком "X-Update: 1". Например, так:
curl -H "X-Update: 1" www.example.com
Заголовок лучше заменить на любой другой, известный только вам.