среда, 13 февраля 2013 г.

Кэширование в Nginx

В статье посвящённой обратному проксированию в Nginx мы с вами не коснулись одной важной темы — кэширования отдаваемого upstream-серверами контента. Когда клиент выполняет запрос, например, к PHP-сценарию, его обработкой занимается upstream-сервер. Работа сценария часто связана с вызовом других сценариев, запросам к базам данных, выполнении довольно тяжёлых в плане потребления ресурсов сервера операций. И очень часто вся эта «каша» заваривается для того, чтобы просто отдать клиенту сформированную страницу; т. е. следующий запрос к этому же сценарию с теми же параметрами запустит ещё один процесс обработки с точно такими же условиями и результатами. А что будет с сервером, когда таких запросов будет несколько десятков в секунду? Несколько сотен? На эти вопросы и на то, как с этим жить, имея в распоряжении Nginx, попытаемся ответить в этой статье.
Следуя уже сложившейся в последнее время в этом блоге традиции, я постараюсь построить заметку в виде небольшого эксперимента, в ходе которого мы с вами будем наблюдать за происходящим. Итак, поехали.

Исходные данные

В качестве PHP-сценария для проведения тестов использовался небольшой скрипт, выбирающий все строки из таблицы БД MySQL и выводящий результаты при помощи var_dump ():
Структура таблицы test1 БД следующая:
Таблица содержит 10000 записей, где в каждом поле name записан MD5-хеш случайного числа в диапазоне от 0 до time (). URL сценария, работающего под Apache — http://test.ashep:80/test.php. Давайте посмотрим при помощи siege как сервер будет обрабатывать запросы к этому сценарию.

Прямые запросы к Apache

Эмулируем 10 серий по 10 одновременных запросов:
Сервер успешно обработал все запросы, однако время на обработку каждого составило в среднем 10,3 секунд.

Проксирование через Nginx

Теперь создадим реверс-прокси сервер в Nginx так, как мы это делали в предыдущей статье, в качестве upstream-сервера будем использовать наш Apache по http://test.ashep:80.
Повторим тест, на этот раз уже через Nginx:
Результаты примерно те же. Логично, поскольку Nginx всего лишь транслирует запросы к upstream-серверу, ничего при этом не кэшируя.

Кэширующее проксирование через Nginx

И теперь самое интересное. Прежде, чем можно будет оперировать кэшированием в настройках серверов Nginx, сперва нужно определить место для хранения и параметры кэша Nginx. Кэшей в Nginx можно определить больше одного, каждый с нужными вам параметрами и затем использовать их в зависимости от ситуации в том или ином месте конфигурации сервера.
Определять кэш можно лишь в контексте секции http, которая, например, в моём Debian описана в /etc/nginx/nginx.conf. Для определения кэша используется опция proxy_cache_path, которая имеет следующий формат:
В квадратных скобках приведены необязательные параметры. Теперь обо всём по порядку:
  • path определяет место в файловой системе, где будет храниться кэш. Кэш в Nginx хранится в виде обычных файлов, каждый из которых хранит содержимое ответа на какой-то запрос. URL запроса хешируется в MD5 и полученная строка используется в качестве имени файла кэша, а также ключа, по которому Nginx будет отыскивать нужный фрагмент кэша;
  • при помощи levels можно определить количество уровней вложенности каталогов с файлами кэша. Формат описания уровней может быть одним из: 'X', 'X:X' или 'X:X:X', что соответственно определяет один, два или три уровня вложенности каталогов. Каждая 'X' является единицей или двойкой и определяет количество символов в имени каталога соответствующего уровня;
  • значением параметра keys_zone определяется имя кэша (zone_name), на которое можно ссылаться из других участков конфигурации сервера, а также её размер (zone_size);
  • при помощи необязательного параметра inactive определяется время жизни объектов кэша, если к ним не было запросов. Т. е. если в течение указанного периода времени объект кэша ни разу не запрашивался — он подлежит удалению. Значение параметра inactive по умолчанию равно 10 минутам (10m);
  • значение необязательного параметра max_size определяет размер кэша, больше которого ему не будет позволено «раздуваться».
В ходе моих экспериментов, рассматриваемых в этой заметке, я использовал следующее значение опции proxy_cache:
Приведённой выше строкой создаётся двухуровневый кэш в каталоге /var/cache/nginx с именем 'default' и размером 100 мегабайт. Теперь определённый кэш default можно использовать в конфигурации серверов Nginx. Слегка дополненная конфигурация сервера, приводившаяся выше:
Обратите внимание на две новых опции. При помощи параметра proxy_cache мы указываем Nginx какой кэш необходимо использовать при кэшировании данных от upstream-сервера, в данном случае — это 'default', определённый ранее в /etc/nginx/nginx.conf. Опция proxy_cache_valid определяет время в течение которого не устаревшими будут считаться объекты кэша, полученные полученные в результате ответов upstream-сервера. Формат опции следующий:
Таким образом ответы upstream-сервера с кодами 200 и 302 будут кэшироваться на 10 минут, а ошибки 404 — в течение одной минуты.
Сохранив конфиг-файлы и перезапустив Nginx, попробуем провести нагрузочное тестирование с включённым кэшированием:
Среднее время ответа от сервера составило 0,73 секунды. Неплохо, правда? ;)

  • adc-lj5 дней назад
    К своему стыду не знаю регэкспы. Подскажите, плиз, где можно почитать про них, очень желательно на русском? В основном интересуют для применения в nginx.
  • 169016
    Роман Жуков3 месяца назад
    Все сделал по мануалу- но не работает.. пишет при рестарте "proxy_cache" zone "default" is unknown in /etc/nginx/nginx.conf:825 configuration file /etc/nginx/nginx.conf test failed Куда копать?.. Кстати, можно к Вам обратиться за настройкой VPS сервера? оптимизация очень нужна.. Естественно, не бесплатно =).. а то толкового специалиста- очень тяжело найти...
    • 168188
      Alexander Shepetko3 месяца назад
      Прежде чем помочь вам определяться с направлением копания, хотелось бы увидеть конфиг полностью. Исходя из текста ошибки очевидно, что у вас не определена зона 'default' параметром proxy_cache_path. Лучше всего выложите конфиг на какой-нибудь pastebin и дайте ссылку, так легче будет диагностировать. Насчёт помощи в оптимизации VPS: увы, пока помочь не смогу.
  • 0
    BuxarNET7 месяцев назад
    А как быть если нужно кеш отдавать только просто посетителям, но если пользователь залогинировался, что бы динамику отдавать?
  • 0
    Kor-Elf12 месяцев назад
    Наконец-то разобрался, как кэшировать в nginx, спасибо за статьи!
  • 0
    Константингод назад
    Подскажите как записать конструкцию location / { proxy_pass http://test.ashep:80; } если на сервере есть два сайта и по ip ничего не выдается, а nginx должен работать как кэширующий прокси на другом сервере. Вариант с указанием ip не работает. location / { proxy_pass http://xxx.xxx.xxx.xxx:80; } Планируется что DNS, настраиваемого домена, должен указывать на кэширующий сервер, т.е. прописать имя сайта я в proxy_pass не могу. Вариант с поддоменами выглядит некрасиво. Правильно ли я понимаю что единственный вариант правильно перенаправить запрос на нужный ip - это прописать в hosts кэширующего сервера домен и ip основного сервера, а в конфигурации написать proxy_pass http://domen.ru/?
  • 0
    /bin/userгод назад
    > А раз права не защищены — пользуйтесь все на здоровье ;) К сожалению, законы о авторских правах немного другого мнения: по умолчанию все права - у автора. А если кто без лицензии взял - он, стало быть, пират. Ну вот такие вот законы протолкали господа демократы, увы.
  • 0
    Qazгод назад
    Статья не плохая, но почему не освещены нюансы работы с cookies при такой схеме?
  • 0
    /bin/userгод назад
    > Даже без лицензий ;) Нынче если брать без лицензий - к сожалению можно нарваться на проблемы. Ну вот вы - добрый. А вот кто-то еще - менее добрый и вот возьмешь у него статью, а потом по судам затаскают. Поэтому хорошо бы явно и прозрачно указывать правила игры. Ну, чтобы можно было понимать - что льзя, что нельзя.
    • 0
      ashepгод назад
      /bin/user, у меня нигде на сайте не написано о том, что права защищены. А раз права не защищены - пользуйтесь все на здоровье ;)
  • 0
    Dmitry Paskalгод назад
    Александр, посмотрите в сторону creative commons. Публиковали бы статьи с соответствующей лицензией - wikidadmin мог бы их взять и доработать. http://creativecommons.org/ - там информация, для wordpress есть плагин с таким же названием, в пару кликов добавляет информацию о лицензии для поисковиков и людей.
    • 0
      ashepгод назад
      Дмитрий, да я ж не возражаю, пусть берут кому нужно, дорабатывают, переписывают. Не жалко совершенно. Даже без лицензий ;)
  • 0
    Aleksdemгод назад
    Конечно статьи, людей перестали продавать уже давно :D
  • 0
    Сергей.год назад
    Отлично. Доступно и "понимабельно". Спасибо.
  • 0
    ashepгод назад
    Меня или статьи? :)
  • 0
    Aleksdemгод назад
    Классная серия статей у вас. Были бы деньги - выкупил бы. :)

Комментариев нет:

Отправить комментарий