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