Самая понятная инструкция по настройке кэширования на OpenLiteSpeed с применением плагина для WordPress

Faster than a speed of lightВ одной из своих недавних статей я поделился опытом переезда с HTTP-сервера Apache на HTTP-сервер OpenLiteSpeed. Преимуществ переезда оказалось много. Производительность блога выросла: странички стали загружаться посетителям куда быстрее, особенно с использованием современных протоколов, сервер начального уровня оказался способен выдержать несравнимо больший объем единовременных посетителей, а ресурсов при всем при этом потребляется чуть ли не вполовину меньше, нежели с решением на основе Apache.

Однако, просто установка OpenLiteSpeed — полдела в плане приведения проекта блога к более современному виду. Есть еще ресурс по оптимизации и улучшения параметров обслуживания. При правильной настройке кэширования страничек производительность может еще подрасти. Но, как оказалось, в плане кэширования веб-страничек присутствует определенная неразбериха. Пришлось разобраться в вопросе досконально.

Типы кэшей

Начнем с того, что уровней кэширования в применении к OpenLiteSpeed (OLS) и клиентскому Веб-браузеру существует несколько. OLS комплектуется плагином кэширования. В OLS плагин имеет ограниченные возможности по настройке, выполняемые в конфигурационном файле. А у его старшего брата LiteSpeed Enterprise доступны полноценные настройки плагина, являющегося частью самого HTTP-сервера. Скудность настроек в целом и вызывает некоторые затруднения по его настройке.

На самом нижнем уровне находится файловый кэш OLS. Файловый кэш использует некоторый объем оперативной памяти исключительно для ускорения отдачи статического контента, будь то картинки или же сохраненные образы динамического контента (например, HTML-страниц).

Другой уровень кэша — пользовательский, им управляет веб-браузер, через который человек просматривает веб-странички. Он тоже вносит существенный вклад в общую производительность, так как вместо запроса к веб-серверу может взять ресурс из собственного кэша.

В природе присутствует еще и кэширование через различные Proxy, включая CDN, но в них глубоко копаться не будем, так как их работа, как и настройка, зависят от конкретного оператора промежуточного кэша и его реализации.

Как работает кэш на стороне OpenLiteSpeed

Суть работы кэша заключается в сохранении динамически сгенерированного контента, в первую очередь — HTML-страниц, и сохранение их в специальной директории. Генерация динамического контента занимает значительно больше ресурсов сервера, чем отдача заранее сгенерированного статического файла. А статические файлы OLS отдает очень быстро и с минимальной нагрузкой на сервер.

Кэширование динамического контента полезно при использовании многочисленных конструкторов сайтов или CMS (Content Management System). Однако, если для каждого пользователя в каждое его обращение к страничке должна быть сгенерирована уникальная HTML-страница, то применение кэширования в таком случае неуместно. Или? При помощи технологии ESI (Edge Side Includes) можно кэшировать не всю страничку, генерируемую динамически, а только ее отдельные части. Таким образом можно снизить нагрузку на сервер, что позволит обслуживать больше запросов при тех же ресурсах. Но ESI отсутствует в OLS, она есть только в LiteSpeed Enterprise версии HTTP-сервера.

Для настройки кэширования в OLS разработаны специальные плагины для основных CMS, например, WordPress (далее будем рассматривать именно его). При помощи плагина для WordPress можно настроить кэш OLS до требуемого уровня. И не только. Помимо настройки непосредственно кэша при помощи плагина можно несколько оптимизировать сам контент: минимизировать текстовые файлы (CSS, JavaScript), соединить текстовые файлы в один (скачивание одного большого файла происходит быстрее, чем десятка более мелких), а при помощи внешних серверов (CDN) оптимизируются картинки.

Но OLS можно использовать и без плагина кэширования для CSM (по сути, плагин кэширования для CMS является интерфейсом для настройки плагина кэширования OLS). В этом случае плагин кэширования OLS можно настроить через конфигурационный файл. А само кэширование через механизм RewriteRule в файлах .htaccess (собственно по таком принципу работает и плагин кэширования для CMS).

Как работает кэш на стороне браузера

Кэширование со стороны браузера заключается в сохранении полученных файлов с веб-сервера в локальный кэш. Как правило, локальный кэш состоит из дискового кэша и его отражения, для наиболее часто используемых файлов, в памяти компьютера.

Динамический и статический контент в кэше браузера
Для браузера нет никакой разницы, каким образом были подготовлены для него файлы на стороне HTTP-сервера. Были ли они отданы просто в виде файла с диска, либо сгенерированы динамически, либо отданы из кэша HTTP-сервера.

История развития браузеров по-настоящему драматична. Она запечатлела взлеты и падения отдельных продуктов и целых компаний. И она нашла свое отражение в том, как браузеры различных производителей и даже разных версий отрабатывали кэширование получаемых с веб-сервера ресурсов. В целом алгоритм выглядит следующим образом:

  • Получить ресурс.
  • Сохранить его в своем кэше.
  • При следующем обращении к ресурсу либо загрузить его с веб-сервера, либо взять из своего локального кэша.

И именно на последнем пункте возникает путаница, так как в далекие времена разные браузеры использовали разные инструкции по тому, как определять — нужно ли скачивать обновленный файл или же можно обойтись его локальной копией.

Сообщить о том, сколько можно хранить локальную копию файла и не обращаться к веб-серверу за его обновлением можно разными способами:

  • Через заголовки Headers, отправляемые вместе с ресурсом:
    • они могут быть сгенерированы веб-сервером;
    • могут быть сгенерированы системой генерации динамического контента, например, PHP или Python;
    • могут быть сгенерированы скриптом на стороне клиента через JavaScript.
  • Через директивы meta в HTML-файле.

В настоящее время большинство браузеров работает на движке Chromium, и ситуация со стандартизацией более-менее устаканилась, поэтому разнообразие команд для управления кэшированием на стороне браузера не велико.

В заголовках HTTP более-менее стандартизировано более сотни директив, что вовсе не означает, что применять можно только их. Если браузер или веб-сервер получают неизвестную ему директиву, то она просто отбрасывается. А воздействие осуществляют только совместимые директивы. Более того, далеко не все директивы заголовков предназначены для выполнения того или иного действия, многие из них сугубо информационные и информируют, например, о типе используемого HTTP-сервера или версии применяемого браузера.

Но в контексте кэширования директив не так много. Итак, браузер должен реагировать на следующие директивы получаемые от веб-сервера:

  • Cache-Control — основная директива объявляются принципы кэширования конкретного ресурса.
  • ETag — хэш ресурса, применяется для идентификации его изменения.
  • Expires — определяет дату и время, после которых закэшированный ресурс должен быть обновлен.
  • Last-Modified — дата и время последней модификации ресурса (по мнению веб-сервера).
  • Pragma — устаревшая и не рекомендуемая к использованию конструкция для определения принципов кэширования ресурса. Вместо нее следует использовать Cache-Control.

Таким образом получается конструкция из четырех директив (Pragma не рассматриваем), где Cache-Control определяет как должна кэшироваться страничка или ресурс в браузере, а ETag, Expires и Last-Modified используются для определения факта того, что закэшированный ресурс устарел и следует проверить наличие обновления на сервере.

Cache-Control

Cache-Control — основная директива заголовков HTTP-сервера определяющая правила хранения ресурса в кэше. Браузер может выполнять директиву и применять предлагаемые настройки, но может и игнорировать их по своему усмотрению (в большинстве случаев все же выполняет, иначе опыт «сёрфер по веб» получит весьма своеобразный). Cache-Control может использовать несколько директив для определения правил кэширования.

max-age

Наиболее часто употребляемая директива означающая сколько в секундах полученный объект может храниться в кэше браузера и использоваться без его повторной загрузки. Минимальное значение 0, максимальное 31536000 (что означает один год). Можно попытаться выставить его и больше, но браузер, скорее всего, просто проигнорирует такое значение.

Max-Age объявляет время, которое считается не с момента получения браузером заголовка, а с момента его генерации веб-сервером. На практике может сложиться ситуация, когда между сервером и браузером присутствует один или несколько внешних сервисов кэширования, например, корпоративный proxy–сервер. В этом случае браузер может использовать директиву Age, если таковая предоставляется, для определения истинного возраста ресурса.

Использование минимального значения 0 означает, что уже в момент получения ресурса он будет считаться устаревшим. И при следующем запросе к этому же ресурсу браузер может запросить его заново.

Cache-Control: max-age=604800

В стандарте существует директива-дубль директивы в виде smax-age применяемый для контроля устаревания ресурса в промежуточных системах кэширования, например, в том самом корпоративном proxy-сервере или CDN.

no-cache и no-store

Директива no-cache приравнивается по действию к max-age=0 и означает, что полученный ресурс следует повторно запросить с веб-сервера при следующем к нему обращении. Но, ресурс все равно сохраняется в локальный кэш браузера, так как если ресурс не был изменен на сервере, то браузер может воспользоваться сохраненной копией из своего локального кэша.

А вот директива no-store как раз информирует браузер, что ресурс не стоит вообще сохранять в локальном кэше и в любом случае получить его еще раз с веб-сервера.

must-revalidate

Директива прямо указывает, что браузер, прежде чем использовать локальную копию ресурса после устаревания, обязан повторно запросить HTTP-сервер на предмет изменения ресурса перед использованием локальной копии. И тут, даже в стандарте, указывается на вольность разработчиков конкретного браузера в плане интерпретации директивы.

Здесь кроется нюанс, который может отрабатываться разными веб-браузерами разными способами. По истечении времени годности ресурса браузер может запросить ресурс повторно, а может предварительно уточнить, а не изменился ли ресурс на веб-сервере и если не изменился, то не скачивать его заново, а использовать локальную копию (именно так все и поступают, хотя стандарт не обязывает к этому). А вот если применяется must-revalidate, то тут уж браузер обязан проверить — изменился ли ресурс прежде, чем принимать решение о его обновлении в своем локальном кэше или использовании формально устаревшей версии.

У must-revalidate есть клон в виде proxy-revalidate, но используется для промежуточных кэширующих сервисов.

private и public

Две директивы-модификаторы устанавливающие контекст кэширования для полученного ресурса. Первая private подразумевает хранение ресурса только в локальном кэше конечного потребителя, а public допускает кэширование ресурса и на промежуточных сервисах кэширования. Предполагается, что в private сохраняются ресурсы получаемы пользователем при аутентифицированном доступе к веб-серверу, например, пользователь залогинился в личный кабинет интернет-магазина или работает в авторизированном режиме с torrent-трекером. А private может хранить в кэше публично-доступные ресурсы, например, изображения на сайте администрации города или онлайн-библиотеки. Однако, при использовании HTTPS-протокола, а он сейчас применяется повсеместно, практически все ресурсы относятся к контексту private, так как не могут быть расшифрованы и использованы другим пользователем.

immutable

Относительно новая директива, обозначающая, что полученный ресурс гарантированно не будет изменен на стороне веб-сервера до истечения срока указанного в max-age. Применяется в основном для уменьшения количества перезапрашиваемых ресурсов с веб-сервера при «мягком» обновлении страницы при нажатии пользователем клавиши F5 (или соответствующего значка).

Применение

В cache-control может записываться сразу несколько директив через запятую.

Cache-Control: max-age=604800, public

Примерно так кэшируется ресурс для «публичного» использования со сроком жизни в неделю.

Cache-Control: private, max-age=0, no-cache, must-revalidate

А таким образом кэшируется страничка для аутентифицированного пользователя. При очередном обращении к страничке браузер обязан провести процедуру проверки обновления ресурса.

Порядок следования директив не имеет значения. Но если директивы будут противоречить друг другу, то будет должно использоваться наиболее строгое из противоречащих правил.

ETag

Специальная директива содержащая хэш (цифровой отпечаток) ресурса. Применяется для целей проверки был ли изменен ресурс на веб-сервере с момента последнего его получения, а в некоторых случаях и для обеспечения неизменности передаваемого ресурса по сети (некоторые ресурсы могут видоизменяться промежуточными сервисами кэширования, например, изображения могут сжиматься). Однако, последняя функция на практике практически не применяется, так как изменить ресурс передаваемый в зашифрованном виде посредством HTTPS не так просто, да и методики генерации хэшей не стандартизирована и может отличаться даже в рамках одного HTTP-сервера.

etag: "5fdc56227ef957f7e752cb06bdf66409"

Пример заголовка ETag, полученного от HTTP-сервера AmazonS3.

Директива etag может быть представлена в так называемой слабой форме. Формирование слабой формы ETag потребляет меньше ресурсов веб-сервера, но одновременно вероятность того, что хэш не изменился, а ресурс, по которому он был создан, изменился, повышается. Слабая форма ETag маркируется дополнительно символами W/.

W/"af9756e8187ca095e1dbbc6ff4540698"

Пример заголовка ETag «слабой» генерации в исполнении Nginx.

ETag может генерироваться как для HTML-ресурсов, так и для всех остальных видов ресурсов обслуживаемых HTTP-сервером.

Expires и Last-Modified

Директива Expires в некоторых населенных пунктах уже считается устаревшей, поэтому если в заголовках встречается указание с Max-Age, то значение Expires не принимается во внимание. Expires содержит указание на конкретную дату и время, когда передаваемый ресурс считается устаревшим. Если значение указано 0, то такой ресурс считается устаревшим сразу же по его получению. Аналогично с указанием значения -1, означающее ошибочную дату. В таком случае считается аналогично, что ресурс устаревает сразу же по его получению браузером.

date: Wed, 08 Feb 2023 18:57:19 GMT
expires: Wed, 08 Feb 2023 20:57:19 GMT
last-modified: Mon, 11 May 2020 15:41:17 GMT

В примере выше приведен Expires на примерно 9 вечера, в то время, когда текущее время около семи вечера. Соответственно, через 2 часа полученный ресурс будет считаться устаревшим и браузеру его нужно будет перезапросить с сервера.

В этом же примере отображена и директива Last-Modified. Директива применяется для передачи сведений о потенциальной дате и времени изменения ресурса. В силу различных обстоятельств веб-сервер не в состоянии достоверно определить когда ресурс в действительности был изменен. Директива Last-Modified используется для определения того, что ресурс был или не был изменен и считается запасным и менее надежным вариантом для случая если ETag отсутствует. По директиве заголовка Last-Modified также могут настраиваться боты–поисковых систем, если большинство ресурсов на сайте не обновлялись очень давно, то, вероятно, что и частота обхода ресурса будет пониженной.

Expires и прочие директивы могут быть переданы не только через заголовки HTTP ответа сервера, но и указана в виде отдельного заголовка в HTML-файле:

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />

Однако, сведения, передаваемые именно через заголовки HTTP ответа, в большинстве случаев будут приоритетны (так как браузеры от Microsoft наконец-то перестали выпускаться на собственном движке, вместо него используется Chromium).

200 versus 304

При обработке запроса браузера (или любого другого клиента), HTTP-север возвращает код выполнения результата. В случае успешного выполнения запроса возвращается код от 200 и до 299. Как правило, используется код 200, означающий успешное выполнение операции. Код 200 наиболее часто используемый код успешного ответа HTTP-сервера на запрос от клиента.

Коды от 300 и до 399 означают переадресацию. Например, код 301 означает, что ресурс был перемещен по другому адресу на постоянной основе, а 302 перемещен на временной основе. А вот код 304, что запрашиваемый ресурс не был модифицирован и клиент может отработать правила If-Modified-Since или If-None-Match. Иными словами, при получении кода 304 браузер может безопасно использовать сохраненную в своем локальном кэше копию ресурса.

Если в кэше браузера уже есть копия ресурса, но еще не истекли Max-Age или Expires, то браузер запросит страничку из своего локального кэша, не отправляя запрос на веб-сервер. И ее код будет тоже 200, словно она была получена с HTTP-сервера. Что несколько путает, особенно если не обращать внимания на дополнительные указания откуда был получен ресурс (либо из памяти, либо с диска).

В чем же различие между 200 и 304, если они оба позволяют использовать кэширование? Разница в том, что при ответе 200 следом отдается и сам ресурс, а при ответе 304, ресурс веб-сервером не отдается. Соответственно, если HTTP-сервер обучен отдавать 304-й код, то он сможет выдержать несколько большую нагрузку при наплыве посетителей, постоянно получающих ресурсы с сервера (например, это новостной ресурс и клиент перелистывает его страница за страницей, где 80% ресурсов могут быть использованы повторно из кэша браузера). Попутно экономится еще и трафик, так как ответы 304 меньше по размеру ответов 200, поскольку не содержат сам запрашиваемый ресурс.

Какой из вариантов предпочтительней?

На этот вопрос нет однозначного ответа, так как он сильно зависит от того, для каких целей применяется кэширование. Если ресурсы на сервере меняются нечасто, то имеет смысл использовать большие значения Max-Age, заставляя тем самым браузер использовать кэширование максимально полно. Однако если ресурсы динамичны, то имеет смысл задуматься о небольшом Max-Age или же вообще отключить кэширование на стороне браузера и полагаться на постоянную ревалидацию ресурса браузером (с кодом 304).

Expires: Wed, 11 Jan 1984 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, max-age=0
Pragma: no-cache

Выше приведен пример максимально доступно объясняющий, что ресурс нужно перепроверить при следующем к нему обращении.

При разработке плана кэширования ресурсов веб-сервера можно применить гибкую схему по разделению времени кэширования для различных разделов сервера или различных типов ресурсов. Например, на такие ресурсы, как шрифты или архивы документов, можно установить максимальное значение Max-Age, а вот для HTML-страниц минимальный. В любом случае необходимо не попасть в ловушку и не установить слишком большое время кэширования для ресурсов, которые могут поменяться куда раньше. К примеру, если установить срок «жизни» для основного файла со стилями сайта месяца в два, а затем внести в него изменения, то добрая половина всех, кто посещал сайт в предыдущие периоды, рискуют использовать старый стиль до тех пор, пока не истечет срок кэширования или пользователь не применит мягкую перезагрузку по F5.

А что же по времени?

Вопрос актуален. Логика подсказывает (и в конечном итоге она права), что использование ресурсов из кэша быстрее, чем даже их ревалидация на веб-сервере. Однако, в реальности цифры замеров могут оказаться более, чем интересными. К примеру, я тестировал время получения ресурсов с моего веб-сервера, располагающемся, как ныне принято говорить, «в другом городе» за более чем 600 км от меня. Измерения проводились по данным в «инструменте разработчика» браузера.

HTML–файл получен с веб-сервера за 14 мс (код 200), этот же файл валидирован за 13 мс (код 304), а загружен из дискового кэша за 15 мс (код 200).
JPG–файл получен с веб-сервера за 5 мс (код 200), этот же файл валидирован за 6 мс (код 304), а загружен из кэша памяти за 0 мс (код 200).

Полученные результаты лишь подтверждают, что современные каналы связи творят чудеса, а сжатие данных еще больше ускоряют получение контента. И особой разницы нет, перекачивать ресурс заново при каждом обращении или же использовать различные варианты кэширования. С другой стороны, и сам инструмент для измерения не самый точный, а если прогнать несколько испытаний кряду, то средние значения покажу, что быстрее всего получить ресурс с локального кэша, затем валидировать его с веб-сервером и получить его снова из локального кэша, ну и самый долгий путь — скачать ресурс с веб-сервера.

Версиализация ресурсов и запросы

Для того, чтобы избежать проблем с излишне большими сроками кэширования применяются следующие трюки. Адрес к ресурсу можно прописать с учетом запроса, например, mysuper.site/main.css?a=b. Все, что идет после знака вопроса, является частью запроса отправляемого по методу GET. И если у вас поменялся ресурс, у которого установлен слишком большое время жизни, то одним из способов заставить клиентов его перезапросить — прописать все ссылки на него через формат запроса.

Альтернативным способом является применение версий в наименовании файла ресурса, например, mysuper.site/js/jquery-3.5.1.min.js. А в случае его изменения просто меняется имя файла в соответствии с новой версией, и правятся ссылки на ресурс.

В обоих случаях необходимо учитывать, что придется изменить все ссылки на ресурс во всех ресурсах сайта, в которых присутствуют такие ссылки. Поэтому следует с разумной осторожностью определять политики кэширования для ресурсов веб-сервера. Особенно, что касается HTML-страниц. Ведь если разрешить браузеру положить HTML-страницу в кэш на год, то кроме как перезагрузить ее по F5 на стороне клиента, другого способа обновить ее содержимое у клиента нет. А если это заглавная страница с новостями?

Практика применения

На диаграмме ниже приведен пример типового алгоритма определения политики кэширования ресурсов веб-сервера. Политика может быть разработана как целиком для всех ресурсов, так и по отдельным их видам или даже разделам сайта. Современные веб-серверы позволяют гибко настраивать кэширование на стороне клиента посредством заголовков.

Диаграмма выбора типа политики кэширования

Диаграмма выбора типа политики кэширования на стороне клиента

В расчет стоит принимать в том числе и специфические части веб-сайта. Например, если установить политику кэширования для изображений с длительным временем жизни, то могут перестать работать счетчики посетителей основанные на отображении какого-то изображения на сайте. Такие ресурсы необходимо обрабатывать при помощи динамического кода JavaScript на стороне клиента, но и в таком случае при запросе удаленного ресурса при неграмотно сформированном запросе есть риск не получить требуемый результат из-за внутреннего кэширования.

Соглашусь, что счетчики сейчас пишут более умело и они ловко обходят все встречающиеся по пути кэши. Но встречаются и более интересные случаи. Например, плагин WordPress Popular Posts хоть и отрабатывает просмотры страниц при помощи JavaScript, но при слишком длительном кэшировании (более 12 часов) не может адекватно обновить статистику просмотра страниц. Проблема заключается в настройках безопасности WordPress и методе обновления статистики по страницам. В плагине используется обращение к ресурсам WordPress через RESP API, но доступ к нему ограничивается при помощи короткоживущего токена (время жизни 12 часов). При генерации динамической HTML–страницы в нее встраивается токен для обращения к REST API через JavaScript. Но если страница была закэширована на срок превышающий срок жизни токена, то запросы плагина будут теряться, а статистика им предоставляемая окажется недостоверной. Аналогичные проблемы могут возникать и с другими «активными» компонентами страницы и сайта.

Настройки OpenLiteSpeed

В OpenLiteSpeed, в отличие от его старшего брата, отсутствует технология ESI, поэтому настроить кэширование можно только для всего ресурса в целом, нельзя закэшировать только его часть.

Пометка ресурсов через ETag в OLS настраивается довольно просто. В административной консоли присутствует только одно место, где включается или отключается настройка ETag — настройка сервера целиком. На уровне виртуального хоста или контекста, по крайней мере в версии OLS 1.7 отдельно настроить ETag нельзя.

OLS Static File Optimization

Настройки генерации ETag и оптимизации отправки для статических файлов

Как видно из названия группы настроек, ETag в OLS генерируется только и исключительно для статических ресурсов. А сама настройка регулирует способ, которым генерируется сам хэш ETag. Для расчета хэш-а могут включаться файловый дескриптор (iNode), время модификации файла и его размер. Если выбрать None, то ETag не будет генерироваться и присылаться вместе с заголовками HTTP.

В стандартах нет требования к способу генерации хэш-а для ETag, но он должен быть более-менее уникальным для ресурса в пределах всего веб-сервера и изменяться, если сам ресурс фактически изменился. В случае использования нескольких физических HTTP–серверов в кластере, рекомендуется отключать iNode, так как на разных серверах одна и та же версия файла будет иметь различные файловые дескрипторы.

Поскольку ETag используется как наиболее надежный признак для проверки отличия ресурса в локальном кэше и на веб-сервере, то функцию генерации ETag имеет смысл держать включенной. Для динамически генерируемого контента формирование ETag находится на плечах самого генератора, ведь только ему известно, изменился ли ресурс или нет.

В этой же группе можно настроить и внутренний кэш HTTP-сервера, который кэширует статические файлы в памяти для ускорения их обслуживания (одна из причин, почему OLS показывает высокие результаты производительности на синтетических тестах). Параметры имеет смысл трогать на серверах с нагрузкой выше среднего.

В отличие от ETag параметр Expires можно настроить как на уровне сервера целиком, так и на уровне виртуального хоста. Настройки, сделанные на уровне виртуального хоста, переопределяют настройки на стороне сервера.

Настройка Expires

Настройка Expires

В группе настроек Expires можно включить или отключить выдачу заголовков связанных с Expires, можно установить общее правило для всех ресурсов, а в самом нижнем поле допускается детализировать значения Expires для каждого из типов MIME-ресурсов. Они перечисляются через запятую и переопределяют значение для общего правила.

image/*=A604800, text/css=A7200, application/x-javascript=A604800, application/javascript=A604800, font/*=A31536000, application/x-font-ttf=A31536000, text/javascript=A604800, application/x-font-woff=A31536000

В перечислении типов можно использовать звёздочки, так для установления единого значения Expires для всех изображений можно использовать тип image/\*, что вполне удобно. В примере выше для ресурсов, которые меняются очень редко, например, шрифтов, установлено максимальное время годности ресурса в один год (значение Expires указывается в секундах). А для ресурсов, которые могут быть изменены, срок жизни в кэше браузера установлен существенно меньше. И, наконец, для HTML-страниц срок годности не определен и вовсе.

OLS имеет возможность указать значение Expires двумя способами:

  • С отсчитыванием значения начиная с момента запроса клиентом ресурса, а точнее его отдачи клиенту. Для этого используется модификатор A перед числовым значением, например, A600 устанавливает время «свежести» ресурса в 10 минут с момента его отдачи сервером.
  • С отсчитыванием значения начиная с момента модификации файла ресурса. Для этого используется модификатор M перед числовым значением.

Использовать модификаторы стоит с умом. Для статического файла с установленным модификатором M может наступить момент, когда он всегда будет отдаваться клиенту уже просроченным, так как он сам был модифицирован довольно давно.

Ресурсы, генерируемые динамически, аналогично обрабатываются через Expires, но у них отсутствует время модификации (это забота уже движка генерации), а тип Expires будет использоваться в соответствии с MIME-типом самого ресурса. И тут присутствует место для путаницы.

Например, если динамически генерируется HTML-файл и его тип text/html, но при этом в настройках сервера не задан Expires для этого типа (или же общая настройка Expires для всех типов ресурсов), то в заголовках не будет передано ничего, что относится к меткам времени генерации ресурса и его времени годности. В этом случае ресурс будет перезапрошен с веб-сервера при следующем обращении. Однако если установить общую настройку Expires для всех типов ресурсов, то она покроет и все динамические ресурсы и тут легко попасть в ловушку, когда выставляется очень длительное время годности для короткоживущего ресурса, например, HTML-страницы.

Далее, Expires влияет не только на само значение директивы Expires, но и на модификатор Max-Age, устанавливая его значение равное установленному Expires. И это необходимо учитывать, так как настройка действует и для статических и для динамически генерируемых ресурсов. Тем не менее, если движок ответственный за генерацию контента будет использовать свои заголовки, то он их переопределит однозначным образом (в эту же категорию попадают и системы кэширования динамического контента).

В OLS кэширование динамического контента выполняется при помощи своего плагина. Он обладает настройками, которые можно изменять, как через интерфейс, так и посредством редактирования основного файла настроек HTTP-сервера. Между тем, если для управления динамическим контентом используется поддерживаемая CMS, то для настроек плагина динамического кэширования лучше использовать соответствующий плагин для CMS.

Настройки LiteSpeed Cache Plugin for WordPress

Плагины для настройки кэширования динамического контента для HTTP-серверов семейства LiteSpeed существуют под все основные актуальные CMS. Но управлять кэшированием можно и без плагина, так как вся настройка и «общение» плагина для CMS с плагином кэширования HTTP-сервера идет через директивы .htaccess файлов.

Помимо управления непосредственно кэшированием динамически формируемых HTML-страничек, плагин предлагает функции по минификации и объединению CSS и JavaScript файлов. Что положительно сказывается на скорости загрузки и отображения контента. В качестве дополнительного сервиса плагин может размещать ресурсы на совместимых CDN-ресурсах, а заодно оптимизировать изображения (опять же при помощи совместимых CDN) конвертируя их в современные форматы (преимущественно WebP). Ну и в качестве бонуса, плагин, по крайней мере для WordPress, а далее рассматривать будем именно его, может использовать различные трюки для ускорения отображения страницы и получения повышенного рейтинга у Google типа «ленивой» загрузки изображений. Плагины постоянно дорабатываются, поэтому вероятно появление и новых функций.

Плагин для WordPress может работать и без HTTP-сервера семейства LiteSpeed, но в таком случае не будет доступна его основная функция в виде кэширования динамически формируемых страничек.

Настройки плагина

Экран выбора групп настроек

Для первоначальной настройки достаточно воспользоваться мастером настройки плагина. В базовой поставке доступно 5 настроек и плагин предлагает по умолчанию сразу же «продвинутый» вариант, тем не менее я бы предложил начинать с «базового» варианта, а затем уже постепенно добавлять очередной круг настроек оптимизации. Например, бессмысленно хранить отдельный кэш для мобильных устройств, если отображение на мобильном формируется исходя из размера экрана при помощи CSS или включать оптимизацию картинок, если они и так были оптимизированы в ручном режиме, даже если и использовались форматы jpg, png и gif.

Настройки выбора TTL

Интерфейс настройки TTL в плагине

В плагине кэширования LiteSpeed для WordPress очень много настроек, большинство из которых работают довольно сносно при использовании стандартизированных настроек из поставки. Тем не менее при настройке плагина имеет смысл перепроверить вкладку TTL в интерфейсе плагина. Вкладка отвечает за время жизни закэшированного динамического контента на стороне сервера. Напомню, что динамический кэш в LiteSpeed работает путем сохранения сгенерированных динамически HTML-страничек и с последующей их выдачей клиентам. При большинстве изменений производимых в WordPress, например, редактировании страницы — кэш динамического контента сбрасывается и генерируется заново при обращении клиента к конкретному ресурсу, но и у самой закэшированной странички может быть свой срок жизни (тут важно не путать срок жизни кэша на стороне сервера и в браузере).

Выше я уже приводил пример проблем, которые могут возникать в плагине WordPress Popular Posts и аналогичных при использовании кэширования динамического контента. Поэтому настройки TTL именно то место, на которое стоит обратить внимание. Тут как раз устанавливаются значения сохранения статического кэша страничек до его автоматической перегенерации. Допустим, устанавливаем значение TTL для обычных страниц на 60 секунд. При первом обращении к странице она будет сгенерирован и сохранен в директории на сервере. При всех последующих запросах к этому ресурсу HTTP–сервер будет отдавать именно закешированную и сохраненную страничку до тех пор, пока не истечет ее TTL в 60 секунд. После истечения TTL закэшированный файл будет удален и произведена новая генерация страницы. И так по кругу.

Настройка кэша браузера

Настройка кэша браузера в плагине

В настройках плагина для WordPress присутствует и потенциальная возможность включения кэширования на стороне браузера. Пользоваться ей стоит лишь в том случае, если нет доступа к настройкам сервера. В противном случае настройку кэширования на стороне браузера необходимо выполнять при помощи настроек сервера (те самые Expires и Max-Age).

Кстати, многие пользователи групповых хостингов, где размещаются только сайты на конкретных CMS, с негодованием отмечают, что плагин кэширования LiteSpeed встраивается в их CMS без их на то ведомо. Ситуация не самая приятная, но хостеры поступают из лучших (для себя) побуждений стимулируя применять кэширование и уменьшать тем самым пустую нагрузку на свои сервера. Поэтому если вдруг в вашей панели управления появился плагин LiteSpeed, то имеет смысл его настроить, чем попытаться от него избавиться.

Дополнительные заголовки

В некоторых случаях необходимо либо изменить, либо добавить новые заголовки для всех или некоторых ресурсов. В OLS этот вопрос решается через использование контекста или нескольких контекстов. Контексты можно определить сразу для ресурсов, для иерархии директорий или выбрать куда более хитроумные комбинации.

Вносимые через контексты измерения имеют больший приоритет, нежели задаваемые в прочих настройках OLS, тем не менее рекомендуется делать unset заголовков, которые переопределяются и set новых заголовков.

Можно ли получить код 304 с WordPress и OpenLiteSpeed?

Краткий ответ, к сожалению нет. Развернутый ответ. В силу того, что ETag в OpenLiteSpeed работает только со статическими ресурсами, а плагин для WordPress не позволяет генерировать и проверять ETag, то получить 304 код нельзя. Полагаться на Last-Modified в этом случае тоже нельзя, так как для динамического контента сервер не может однозначно ответить, какая у него в действительности метка времени модификации. Установить ETag или Last-Modified через сторонний плагин для WordPress или прописать строки вывода требуемых заголовков в теме (header.php) WordPress можно, но они не будут обрабатываться HTTP-сервером так как он про эти заголовки ничего не знает. Получается замкнутый круг. HTTP-сервер не генерирует необходимые метки для проверки факта изменения динамического ресурса, соответственно нет нормального способа заставить его вернуть код 304. С другой стороны, такое поведение не является ненормальным или ошибочным, сайт работать будет и практически не хуже, чем при использовании механизма перепроверки ресурса.

 



Подписаться
Уведомить о
guest

1 Комментарий
Старые
Новые
Межтекстовые Отзывы
Посмотреть все комментарии
@allexpogoda
@allexpogoda
3 месяцев назад

Здраствуйте Владислав! Прошу Вас помочь с настройкой сервера на openlitespeed