Настроить кэширование файлов nginx
NGINX позволяет значительно ускорить процесс загрузки страницы, не обращаясь к бэкэнду, а выдавая готовый html из кэша. Для работы данной функции необходимо, чтобы веб-сервер был версии 0.7.44 и выше (проверить можно командой nginx -v).
Для FastCGI кэш задается с помощью опций fastcgi_cache_*. Для запросов к бэкэнду с помощью proxy_pass — proxy_cache_*.
Сброс кэша
Удалить кэш на стороне сервера nginx мы можем только для бэкэнда. Для статики нужно удалять кэш в самом браузере (например, в настройках или с помощью дополнений).
Для сброса кэша мы просто должны удалить содержимое каталога, который прописан в опции proxy_cache_path или fastcgi_cache_path — в нашем случае, это /var/cache/nginx и /var/cache/fastcgi соответственно.
а) для proxy_cache_path:
б) для fastcgi_cache_path:
Настройка nginx для проекта на php
В файл /etc/hosts (добавляем):
(Не забудьте создать папку /var/spool/nginx/cache и установить для нее пользователя, под которым запускается nginx)
В папке /etc/nginx/conf.d/ создаем конфиги для виртуальных хостов
Пример кофига (/etc/nginx/conf.d/myproject.conf):
Устанавливаем тестовый проект на php в /var/www/myproject. Исходный код примера можно посмотреть и скачать здесь.
Запускаем nginx. Для RedHat-подобных систем это выглядит приблизительно так:
Что такое Nginx cache и как он работает?
Для удобства можно вынести конфигурацию в отдельный файл, например “/etc/nginx/conf.d/cache.conf”. Давайте рассмотрим директиву “proxy_cache_path”, которая позволяет настроить параметры хранения кэша.
“/var/lib/nginx/proxy_cache” указывает путь хранения кэша на сервере. Именно в эту директорию nginx будет сохранять те самые файлы с ответом от бэкенда. При этом nginx не будет самостоятельно создавать директорию под кэш, об этом необходимо позаботиться самому.
“levels=1:2” — задает уровень вложенности директорий с кэшем. Уровни вложенности указываются через “:”, в данном случае будет созданы 2 директории, всего допустимо 3 уровня вложенности. Для каждого уровня вложенности доступны значения от 1 до 2, указывающие, как формировать имя директории.
Важным моментом является то, что имя директории выбирается не рандомно, а создается на основе имени файла. Имя файла в свою очередь является результатом функции md5 от ключа кэша, ключ кэша мы рассмотрим чуть позже.
Давайте посмотрим на практике, как строится путь до файла кэша:
“keys_zone=proxy_cache:15m” параметр задает имя зоны в разделяемой памяти, где хранятся все активные ключи и информация по ним. Через “:” указывается размер выделяемой памяти в Мб. Как заявляет nginx, 1 Мб достаточно для хранения 8 тыс. ключей.
“max_size=1G” определяет максимальный размер кэша для всех страниц, при превышении которого nginx сам позаботится об удалении менее востребованных данных.
Также есть возможность управлять временем жизни данных в кэше, для этого достаточно определить параметр “inactive” директивы “proxy_cache_path”, который по умолчанию равен 10 минутам. Если в течение заданного в параметре “inactive” времени к данным кэша не было обращений, то эти данные удаляются, даже если кэш еще не “скис”.
Что же из себя представляет этот кэш? На самом деле это обычный файл на сервере, в содержимое которого записывается:
• ключ кэша;
• заголовки кэша;
• содержимое ответ от бэкенда.
Если с заголовками и ответом от бэкенда все понятно, то к “ключу кэша” есть ряд вопросов. Как он строится и как им можно управлять?
Для описания шаблона построения ключа кэша в nginx существует директива “proxy_cache_key”, в которой в качестве параметра указывается строка. Строка может состоять из любых переменных, доступных в nginx.
Символ “:” между параметром куки и get-параметром используется для предотвращения коллизий между ключами кэша, вы можете выбрать любой другой символ на ваше усмотрение. По умолчанию nginx использует следующую строку для формирования ключа:
Следует отметить следующие директивы, которые помогут более гибко управлять кэшированием:
proxy_cache_valid — Задает время кэширования ответа. Возможно указать конкретный статус ответа, например 200, 302, 404 и т.д., либо указать сразу все, с помощью конструкции “any”. В случае указания только времени кэширования, nginx по дефолту будет кэшировать только 200, 301 и 302 статусы.
proxy_cache_lock — Эта директива поможет избежать сразу нескольких проходов на бэкенд за набором кэша, достаточно установить значение в положении “on”. Все остальные запросы будут ожидать появления ответа в кэше, либо таймаут блокировки запроса к странице. Соответственно, все таймауты возможно настроить.
proxy_cache_lock_age — Позволяет установить лимит времени ожидания ответа от сервера, после чего на него будет отправлен следующий запрос за набором кэша. По умолчанию равен 5 секундам.
proxy_cache_lock_timeout — Задает время ожидания блокировки, после чего запрос будет передан на бэкенд, но ответ не будет закэширован. По умолчанию равен 5 секундам.
proxy_cache_use_stale — Еще одна полезная директива, позволяющая настроить, при каких случаях возможно использовать устаревший кэш.
В данном случае будет использовать устаревший кэш в случае ошибки подключения, передачи запроса, чтения ответа с сервера, превышения лимита ожидания отправки запроса, чтения ответа от сервера, либо если в момент запроса происходит обновление данных в кэше.
proxy_cache_bypass — Задает условия, при которых nginx не станет брать ответ из кэша, а сразу перенаправит запрос на бэкенд. Если хотя бы один из параметров не пустой и не равен “0”. Пример:
proxy_no_cache — Задает условие при котором nginx не станет сохранять ответ от бэкенда в кэш. Принцип работы такой же как у директивы “proxy_cache_bypass”.
Хранение кэша в оперативной памяти
Мы можем значительно ускорить процесс записи и чтения информации, если будем хранить кэш в оперативной памяти.
Создаем обычный каталог, в который будем монтировать часть оперативной памяти:
. и дадим на него полные права:
chmod 777 /var/ramdisk
Монтируем часть оперативной памяти как обычный каталог:
mount -t tmpfs -o size=2G ramdisk /var/ramdisk
* в данном примере мы монтируем 2 Гб оперативной памяти как папку /var/ramdisk. Возможно, правильнее будет заранее убедиться в наличие свободной памяти командой free.
Для автоматического монтирования открываем на редактирование fstab:
ramdisk /var/ramdisk tmpfs nodev,nosuid,noexec,nodiratime,size=2G 0 0
Теперь, когда у нас есть каталог, данные которого хранятся в оперативной памяти, редактируем параметр proxy_cache_path или fastcgi_cache_path в NGINX:
proxy_cache_path /var/ramdisk levels=1:2 keys_zone=all:64m inactive=2h max_size=2g;
fastcgi_cache_path /var/ramdisk levels=1:2 keys_zone=fastcgi:64m inactive=2h max_size=2g;
В жизни каждого проекта настает время, когда сервер перестает отвечать требованиям SLA и буквально начинает захлебываться количеством пришедшего трафика. После чего начинается долгий процесс поиска узких мест, тяжелых запросов, неправильно созданных индексов, не кэшированных данных, либо наоборот, слишком часто обновляемых данных в кэше и других темных сторон проекта.
Но что делать, когда ваш код “идеален”, все тяжелые запросы вынесены в фон, все, что можно, было закэшировано, а сервер все так же не дотягивает до нужных нам показателей SLA? Если есть возможность, то конечно можно докупить новых машин, распределить часть трафика и забыть о проблеме еще на некоторое время.
Но если вас не покидает чувство, что ваш сервер способен на большее, или есть магический параметр, ускоряющий работу сайта в 100 раз, то можно вспомнить о встроенной возможности nginx, позволяющей кэшировать ответы от бэкенда. Давайте разберем по порядку, что это, и как это может помочь увеличить количество обрабатываемых запросов сервером.
Возможные проблемы при кэшировании страниц
Следующая задача, с которой придется столкнуться — это управление кэшированием. Конечно можно установить незначительное время кэша в 2-5 минут и этого будет достаточно в большинстве случаев. Но не во всех ситуациях такое применимо, поэтому будем изобретать свой велосипед. Теперь обо всем по порядку.
Управление сохранением cookie
Управление сбросом кэша
Перед тем как начать писать свое решение, посмотрим, что предлагает nginx из “коробки”. Для сброса кэша в nginx предусмотрена специальная директива “proxy_cache_purge”, в которой записывается условие сброса кэша. Условие на самом деле является обычной строкой, которая при непустом и не “0” значении удалит кэш по переданному ключу. Рассмотрим небольшой пример.
Пример взят с официального сайта nginx.
За сброс кэша отвечает переменная $purge_method, которая является условием для директивы “proxy_cache_purge” и по дефолту установлена в “0”. Это означает, что nginx работает в “обычном” режиме (сохраняет ответы от бэкенда). Но если изменить метод запроса на “PURGE”, то вместо проксирования запроса на бэкенд с сохранением ответа будет произведено удаление записи в кэше по соответствующему ключу кэширования. Также возможно указать маску удаления, указывая знак “*” на конце ключа кэширования. Тем самым нам не нужно знать расположения кэша на диске и принцип формирования ключа, nginx берет на себя эти обязанности. Но есть и минусы этого подхода.
- Директива “proxy_cache_purge” доступна как часть коммерческой подписки
- Возможно только точечное удаление кэша, либо по маске вида “*”
Мы знаем, что nginx кэш — это обычный файл на сервере. Директорию для хранения файлов кэша мы самостоятельно указали в директиве “proxy_cache_path”, даже логику формирования пути до файла от этой директории мы указали с помощью “levels”. Единственное, чего нам не хватает, это правильного формирования ключа кэширования. Но и его мы можем подсмотреть в директиве “proxy_cache_key”. Теперь все что нам остается сделать это:
- сформировать полный путь до страницы, в точности как это указано в директиве “proxy_cache_key”;
- закодировать полученную строку в md5;
- сформировать вложенные директории пользуясь правилом из параметра “levels”.
- И вот у нас уже есть полный путь до файла кэша не сервере. Теперь все, что нам остается, это удалить этот самый файл. Из вводной части мы знаем, что nginx может быть расположен не на машине приложения, поэтому необходимо заложить возможность удалять сразу несколько адресов. Снова опишем алгоритм:
- Сформированные пути к файлам кэша мы будем записывать в файл;
- Напишем простой сценарий на bash, который поместим на машину с приложением. Его задачей будет подключиться по ssh к серверу, где у нас находится кэширующий nginx и удалить все файлы кэша, указанные в сформированном файле из шага 1;
Шаг 1. Формирование файла с путями до кэша.
Обратите внимание, что в переменной “$urls” содержатся url закэшированных страниц, уже в формате “proxy_cache_key”, указанном в конфиге nginx. Url выступает неким тегом для выводимых сущностей на странице. Например, можно создать обычную таблицу в бд, где каждый сущности будет сопоставлена конкретная страница, на которой она выводится. Тогда при изменении каких-либо данных мы можем сделать выборку по таблице и удалить кэш всех необходимых нам страниц.
Шаг 2. Подключение на кэширующий сервер и удаление файлов кэша.
Приведенные примеры несут ознакомительный характер, не стоит использовать их в production. В примерах опущены проверки входных параметров и ограничения команд. Одна из проблем с которой можно столкнутся — это ограничение длины аргумента команды “rm”. При тестировании в dev окружении на небольших объемах это можно легко упустить, а в production получить ошибку “rm: Argument list too long”.
Делаем выводы
Даже если такой подход покажется Вам примитивным, и функциональность его сильно ограниченной, обратите внимание на то, что это работает не просто быстро, а очень быстро!
Узким местом может быть только дисковая система, если кеш «распухнет» до больших размеров и не будет помещаться в дисковый кеш.
PS: Если эта статья будет интересна читателям, я планирую написать вторую часть о применении описанного подхода к кешированию блоков на Zend Framework.
Давно минули те старые добрые времена, когда сайты были сделаны на голом HTML и их страницы весили несколько десятков килобайт. А интернет был на dial-up.
Рассмотрим метод борьбы с этой проблемой посредством вебсервера Nginx. Суть в том, что мы сделаем 2 вещи — сожмём все статические файлы (скрипты, файлы стилей) посредством gzip, и закэшируем их вместе с картинками в кэше браузера посетителя, чтобы они каждый раз не загружались с сайта, а брались прямо из кэша на компьютере посетителя сайта.
Все настройки и команды далее идут для сервера с Centos, однако настройка серверов с другими системами мало чем отличается.
Настройка сжатия данных посредством Nginx.
Открываем файл конфигурации Nginx, расположенный по адресу /etc/nginx/nginx.conf
Настройка кэширования статических файлов в кэше браузера пользователя, посредством Nginx.
В том же файле /etc/nginx/nginx.conf спускаемся ниже, находим конструкцию server для нужного сайта и дописываем туда:
где expires 7d — это количество дней, сколько кэш статических файлов должен храниться на компьютере пользователя. Если вы не вносите правки в css, js, файлы своего сайта и не меняете картинки, то имеет смысл этот параметр увеличить, вплоть до нескольких месяцев или даже до года.
Для наглядности приводим участок секции server из сервера, в котором Nginx был установлен стандартными средствами панели ISPmanager:
А теперь мы добавим сюда expires 7d, теперь это будет выглядеть вот так:
Перезагружаем Nginx командой:
Заходим на свой сайт и радуемся, он теперь стал загружаться в несколько раз быстрее. А вес страниц сайта снизился с нескольких мегабайт до пары десятков килобайт!
Данная статья будет полезна для владельцев виртуальных и выделенных серверов, так как у пользователей виртуального хостинга нет доступа к редактированию конфигурации Nginx. Однако клиенты виртуального хостинга, предлагаемого нашей организацией всегда могут обратиться в службу поддержки, и наши системные администраторы внесут необходимые настройки для вашего сайта.
Настройка кэширования для proxy_pass
Как было сказано выше, для разных методов обращения к серверу, который обрабатывает запрос, нужно использовать разные методы кэширования.
Избавляемся от постоянных запросов к бэкенду через ssi
В переменной $memcache_key мы указали ключ, по которому nginx попробует получить данные из memcache. Параметры подключения к серверу memcache задаются в директиве “memcached_pass”. Подключение можно указать несколькими способами:
• IP адрес и порт;
Если nginx удалось получить ответ от сервера кэша, то он отдает его клиенту. В случае когда данных в кэше нет, запрос будет передан на бэкенд через “@fallback”. Эта небольшая настройка memcached модуля под nginx поможет нам сократить количество проходящих запросов на бэкенд от ssi вставок.
Надеемся, эта статья была полезна и нам удалось показать один из способов оптимизации нагрузки на сервер, рассмотреть базовые принципы настройки nginx кэширования и закрыть возникающие проблемы при его использовании.
Существует мнение, что nginx — отличный инструмент для отдачи статики.
Есть статьи, где описываются настройки sendfile или aio для «улучшения» отдачи.
На Хабре есть чего почитать о настройке proxy_store с proxy_cache для минимизации проблем со стороны мозгов сайта.
Еще в QA иногда возникают вопросы про кеширование картинок, например.
Зачем заниматься этой ерундой! — говорят опытные пользователи — OS лучше вас знает как кешировать файлы! С кешем и префетчем в современных OS, точнее FS, проблем нет! Зачем плодить свои кеши и списки популярных материалов и все такое.
Есть только одно вредное «но» — в среде исполнения nginx (в общем случае Linux) понятие "файл" и вообще «файловая система» — просто понятие.
И однажды, когда я, подмонтировав сервер по sshfs, обновил один скриптик, случилось волшебное:
1. На каждой страничке стало на 4 картинки больше.
2. Сервера сдохли.
Что поделать — картинки хранились на glusterFS. Наступил полный FUSE.
GlusterFS, как и интерфейс FUSE, сильно сжирает производительность, но он того стоит.
Изначально у нас был один сервер. Потом два, второй из который монтировал www с первого по nfs. Потом три, четыре.
Не очень надежно, но так уж исторически сложилось. Для спасения ситуации нужна была некая совершенно прозрачная система, in-place замена nfs. Кластерная ФС.
Сейчас на всех серверах стоит raid 10, и за полтора года эксплуатации он пару раз падал. В том числе совсем. Gluster молча поднимал копию ФС на новой железяке и все продолжало работать. Гластер свою работу знает.
Но на самом деле история начиналось немного не так.
Причина была другая, но решения проблем будет совпадать.
Нет ничего страшнее чем то что "исторически сложилось".
И в одном моем проекте «исторически сложилась» ситуация, когда картинки отдает php.
В свое время нужно было сделать файловый загрузчик с различными ACL, ресайзами и вотермарками. Это было почти 10 лет назад. Механизм прижился и с тех пор не менялся.
Сейчас для решения таких проблем есть много специализированных решений(elliptics, backpack и другие; а еще лучше CDN). Но тратить человекомесяцы на переход не хочется. Спать хочется, а не работать.
Да и php чтука, в принципе, неплохая. Но имеет свои пределы.
Но проблема тормозных бэкендов решена
Хабр, в очередной раз подсказал вариант решения — proxy_store и proxy_cache.
Но proxy_store использовать мне нельзя — сохранить негде, и с proxy_cache тоже проблемы.
Есть одно, большое такое, «но» — много лет назад я уже столкнулся с производительностью отдачи файлов и решил «пускай лучше nginx отдает конечные файлы за меня».
X-Accel-Redirect.
Проблема — nginx не может закешировать ответ из прокси если это не ответ, а команда. X-Accel-Redirect — не кешируется.
Выхода нет?
Исходную проблему зафиксировали
Теперь вернемся к началу топика.
Нам нужно отдать статику, на этот раз без вмешательства «умных» бэкэндов. Просто статику, но с glusterfs.
Директив для кеширования статики просто нет — не предусмотрены. Считается что OS сама не дура. Для статики есть только open_file_cache и настройка самой передачи файлов(sendfile/aio и компания).
Что делать?
Усложним задачу, и попробуем решить проблему исключительно средствами nginx, не внося никаких изменений в другие коды.
обычный конфиг
Пропатченый конфиг
Nginx делает proxy_pass сам на себя, кешируя результат. Возможно тут можно использовать fcgi, но так — нагляднее.
И никакой магии.
В случае с X-Accel-Redirect схема такая:
1. nginx получается запрос
2. пересылает себе, к сожалению запрос полный и реальный.
3. пересылает на прокси
4. получает ответ и отдает файл
5. ответ кешируется
6. .
7. PROFIT
В случае с обычной статикой сложнее — root не заканчивает выполнение, break и return также не работают. Настройка прокси не может находиться внутри условного блока.
Что это дает?
В смысле с X-Accel-Redirect с apache снимается вал запросов. На загруженной системе разница может составить 50 раз.
Но это понятно — php сам по себе, а через апач тем более, не самое реактивное решение.
Latenсy запроса меньше 40мс, лично у меня, не получался (общее время php+gluster).
В случае использования варианта с proxy_cache скорость отдачи приравнивается к скорости отдачи статики.
А что со статикой?
Отдача с gluster — 13мс — это нормальное время для системы без кеша.
Отдача из кеша — 1мс — это замечательное.
Важно учесть — сервера находятся в Германии, а клиенты в России.
Нормальные пинги до сайта 60-100мс.
Так что для клиента ускорение практически не заметно.
Но оно заметно для сервера.
1. Снизилась нагрузка на сервера, в том числе в попугаях Load average и soft-irq.
2. Снизился трафик между серверами (можно решить включив WORM(Write Once Read Many volume), но это уже не «прозрачно»).
3. Все стало работать чуть быстрее.
В итоге работы которые на 10% снизили скорость реакции на клиенте, получились в результате 10-ти кратного ускорения отдачи статики. Что снизило общую нагрузку на сервера примерно раз в 20.
Обратное утверждение, к сожалению, тоже будет верно — сколько не старайся, клиент может и не заметить.
PS: Многие знакомые сисадмины даже не допускали мысли о возможности работы такой схемы. Не позволяет кешировать/проксировать — значит нельзя.
Хорошие программисты не всегда хорошие сисадмины, а сисадмины, обычно, вообще не программисты.
Настоящие герои всегда идут в обход, в брод, и на велосипедах.
PPS: я, кстати, не сисадмин. И, быть может, все сделал не правильно.
Cайт всегда можно разбить на некоторое число независимых блоков, генерацией которых может заниматься (при необходимости) разные сервера.
При этом сборкой блоков в единое целое занимается некий «сборщик» и если любой из блоков по какой-то причине не создан за отведенное ему время, то это еще не повод выдавать клиенту «Gateway timeout» или «Internal Server Error». Можно собрать успешно созданные блоки, а на месте «сбойных» показывать устаревший контент из кеша.
Для реализации такой модели нам понадобиться технология-ветеран Web-разработки: ssi. В качестве «сборщика», как ясно из названия статьи, выступает nginx. «Чудеса» станут возможны благодаря модулю fastcgi_cache.
Кэширование статики
Кэширование статики не имеет никакого отношения к кэшированию ответа от бэкэнда, однако, это тоже позволяет разгрузить сервер. Суть в том, что nginx сам умеет отдавать статические файлы + задавать инструкцию для браузера по ее кэшированию.
Настройка выполняется для каждого виртуального хоста (секция server):
server .
location ~* ^.+\.(css|js)$ root /var/www/site
expires modified +1w;
>
location ~* ^.+\.(jpg|jpeg|gif|png)$ root /var/www/site
expires max;
>
>
* в данном примере мы задаем для файлов изображений (jpg, jpeg, gif, png) кэш до 31 декабря 2037 23:55:55 (max), для файлов css и js — 1 неделя с момента их модификации. Данные настройки мы задаем при помощи параметра expires, который, в свою очередь, задает заголовок cache-control. NGINX будет искать статические файлы в корневом каталоге /var/www/site.
После применяем настройки:
systemctl restart nginx
Мастерим блоки
Блоком будем называть любую логически выделенную часть html-кода без стандартных заголовков html-старницы, например:
Чтоб визуально контролировать состояние свежести каждого из блоков добавим код, наших тестовых блоков вывод времени.
Устанавливаем nginx
Можно ставить стандартный из репозитория/портов… Но если хотите чтоб работала возможность «почистить» любой файл в кеше, придется компилировать.
Нам понадобиться модуль: ngx_cache_purge
Я подробно опишу, как это можно сделать для redhat-подобной системы, а вы уж по аналогии компилируйте под вашу систему.
Это не совсем красивый способ, т.к. полученный в результате .src.rpm не будет содержать файла с модулем ngx_cache_purge. Если для вас, все же, это критично, то здесь можете загрузить «правильный» вариант nginx .src.rpm для ветки 8.xx. Правда я часть ненужных мне модулей закомментировал.
Устанавливаем пересобранный nginx на наш сервер:
Тестируем
Обратите внимание, «каркас» страницы обновляется раз в 10 секунд, остальные блоки обновляются согласно примечаниям под временем создания блока.
Самый большой интерес, на мой взгляд, представляет «Збойный блок». Если вы введете его в режим имитации сбоя, вы все равно будете видеть «несбойную» версию этого блока пока не очистите кеш.
Кроме того, помните, что вы не одни сейчас проводите эксперименты с этой страничкой, если хотите поэкспериментировать — самостоятельно настройте локальную копию примера.
Применение настроек
NGINX настроен. Проверим корректность настроек:
Если ошибок нет, применяем их:
systemctl restart nginx
Теперь заходим на сайт и смотрим в каталог с кэшем — в нем должны появиться каталоги и файлы:
Мы должны увидеть что-то на подобие:
drwx------. 3 nginx nginx 4096 Jan 25 16:09 0
drwx------. 5 nginx nginx 4096 Jan 25 16:09 2
drwx------. 5 nginx nginx 4096 Jan 25 16:15 3
drwx------. 3 nginx nginx 4096 Jan 25 16:09 4
drwx------. 4 nginx nginx 4096 Jan 26 05:08 5
drwx------. 3 nginx nginx 4096 Jan 25 16:09 6
drwx------. 3 nginx nginx 4096 Jan 26 04:18 7
drwx------. 3 nginx nginx 4096 Jan 25 16:10 8
drwx------. 5 nginx nginx 4096 Jan 25 16:15 a
drwx------. 3 nginx nginx 4096 Jan 25 16:09 b
drwx------. 5 nginx nginx 4096 Jan 26 04:19 e
drwx------. 3 nginx nginx 4096 Jan 25 19:55 f
Удаляем страницы из кеша
К сожалению у nginx-а пока что нету родного (штатного) способа удаления страничек из кеша. Иногда это может создавать неудобства.
Если вы добавили при компиляции модуль ngx_cache_purge, то в конфиг (/etc/nginx/conf.d/myproject.conf) добавим приблизительно такую секцию, перед секцией «location / <. » :
С помощью директив allow и deny можно ограничить круг хостов с которых можно «чистить» кеш.
Что такое SSI и как он работает
SSI (Server-Side Includes, включения на стороне сервера) — это некий набор команд, встраиваемых в html страницу, указывающие серверу, что нужно сделать.
Вот некоторый перечень таких команд (директив):
• if/elif/else/endif — Оператор ветвления;
• echo — Выводит значения переменных;
• include — Позволяет вставлять содержимое другого файла в документ.
Как раз о последней директиве и пойдет речь. Директива include имеет два параметра:
• file — Указывает путь к файлу на сервере. Относительно текущей директории;
• virtual — Указывает виртуальный путь к документу на сервере.
Нас интересует параметр “virtual”, так как указывать полный путь до файла на сервере не всегда удобно, либо в случае распределенной архитектуры файла на сервере попросту нет. Пример директивы:
Для того, чтобы nginx начал обрабатывать ssi вставки, необходимо модифицировать location следующим образом:
Теперь все запросы, обрабатываемые location “/”, будут иметь возможность выполнять ssi вставки.
Как же во всей этой схеме будет проходить наш запрос?
- клиент запрашивает страницу;
- Nginx проксирует запрос на бэкенд;
- бэкенд отдает страницу с ssi вставками;
- результат сохраняется в кэш;
- Nginx “дозапрашивает” недостающие блоки;
- итоговая страница отправляется клиенту.
Кэширование персонализированных блоков
Давайте подведем итог, что нам удалось сделать:
- снизили нагрузку на бэкенд;
- научились управлять кэшированием;
- научились сбрасывать кэш в любой момент времени.
Нужно рассмотреть альтернативную подгрузку таких частей страницы. Как всегда это можно сделать множеством способов, например после загрузки страницы отправлять ajax запрос, а на месте персонального контента отображать лоадер. Другим способом, который мы как раз сегодня и рассмотрим, будет использование ssi тегов. Давайте вначале разберемся что из себя представляет SSI, а затем, как мы можем его использовать в связке с nginx кэшем.
Отключение кэширования
Как говорилось выше, в некоторых случаях, кэширование может навредить и на некоторых страницах его стоит отключить. В настройках виртуального хоста, мы можем создать отдельный location, для которого отключиться кэш, например:
* обратите внимание, что в данном примере мы отключаем кэширование как для запросов proxy_pass, так и fastcgi_pass.
При отключении кэширования для статики используем следующую конфигурацию:
server .
location ~* ^.+\.(jpg|jpeg|gif|png|css|js)$ root /var/www/site
expires epoch;
>
>
* expires epoch задаст заголовок сache-control с временем окончания кэша "1 января 1970 00:00:01".
Рекомендации и противопоказания
Кэш — это данные не первой свежести. Это важно учитывать, если мы хотим настроить эффективное кэширование средствами nginx. Мы можем столкнуться с различными проблемами, например, неспособность сервера продлить сессию авторизованного пользователя или отображение старой информации на портале с динамично меняющимся контентом. Чтобы избежать данных проблем, настройка nginx должна быть тесно сопряжена с разработкой сайта. Идеальная работа кэша возможна только при полном понимании внутренних механизмах работы портала, такие как, отправка запросов на авторизацию, продление сессии, обновлении контента — программист может написать для этого запрос по определенным URL, для которого администратор NGINX может отключить кэширование.
Кэширование динамики будет полезно для сайтов с высокой посещаемостью, из-за которой создается высокая нагрузка на сервер и он не может успеть выполнить обработку запросов. Также оно будет полезно для отдельных страниц, содержимое которых меняется очень редко, но отработка скриптов выполняется долго.
Из всего этого можно сделать вывод, что кэширование на стороне сервера NGINX стоит применять только в случае высоких нагрузок и медленной работы сайта из-за долгой работы backend'а.
Включение кэширования
Открываем конфигурационный файл nginx:
* в данном примере мы задали глобальную настройку для кэширования:
- /var/cache/nginx — путь хранения кэша.
- levels — уровень вложенности каталогов. В данном примере мы задаем настройку, при которой в каталог с кэшем будет создан каталог, а в ней — еще один каталог.
- keys_zone — имя зоны в разделяемой памяти, где будет храниться кэш, а также ее размер.
- inactive — задает время, после которого кэш будет автоматически чиститься.
- max_size — максимальный размер данных под кэш. Когда место заканчивается, nginx сам удаляет устаревшие данные.
Создаем каталог для хранения кэша и задаем владельца:
chown nginx:nginx /var/cache/nginx
Настройка кэширования для fastcgi_pass
Настройка fastcgi_cache аналогична proxy_cache и настройки можно сделать по подобию последнего, заменив proxy_ на fastcgi_. Мы разберем основные настройки без подробностей и комментариев.
Открываем конфиг nginx:
* обратите внимание, что мы задали другой каталог и keys_zone.
Создаем каталог для кэша:
chown nginx:nginx /var/cache/fastcgi
Проверяем настройки и применяем их:
systemctl restart nginx
Настройка хостов
Чтобы определенный сайт или отдельная страница кешировала запрос, открываем конфигурационный файл с настройками виртуального домена или хоста, например:
. и добавим к proxy_pass кэширование — мы получим что-то на подобие:
Исключаем лишнее звено
Нам не пригодиться apache, наличие которого, как правило объясняется использованием RewriteRules. В nginx есть аналог mod_rewrite или комбинация location/alias с регулярными выражениями, возможности которых позволяют написать аналог любому RewriteRule от apache. Кроме того в современных фреймворках разбором входного URL может заниматься сам движек (например Zend_Controller_Router_Rewrite в Zend Framework)
В качестве fastcgi-бекенда может использоваться любая платформа. Примеры будут на php, но это не означает что нельзя написать аналогичный код на python-е или perl-е.
Можно еще прописать путь к лог-файлу в php.ini (error_log = /var/log/fastcgi/fastcgi.log), но при этом придется перезагружать php-cgi.
Более продвинутый вариант запуска fastcgi — установка php-fpm.
Учим backend управлять временем кеширования
Дело в том, что в nginx время кеширования указывается в параметре fastcgi_cache_valid 200 0m; и распространяется на все страницы, в которых заголовком оно не переопределено.
В конфиге «по умолчанию» время кеширования я указал равным 0, т.е. кеширование отключено. Но если бекенд сгенерирует заголовок приблизительно такого вида:
либо
То страница nginx-ом будет закеширована на 20 секунд. В php заголовок можно поменять с помощью функции header() (Со слов автора nginx самым приоритетным является «X-Accel-Cache-Control», потом «Cache-Control», потом «Expires»).
Напишем небольшую функцию. котрая будет управлять временем кеширования:
Читайте также: