====== Прозрачное кэширование в 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 Заголовок лучше заменить на любой другой, известный только вам.