Содержание
Прозрачное кэширование в nginx, для всех и каждого
Источник - http://sanmai.livejournal.com/1013539.html
Представим, что у нас есть сайт, на который регулярно даёт ссылки 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
Заголовок лучше заменить на любой другой, известный только вам.
Обсуждение