Контроль срока действия кэша с последней модификацией - PullRequest
15 голосов
/ 18 февраля 2009

В модуле Apache mod_expires есть директива Expires с двумя базовыми периодами времени, доступ и изменение .

ExpiresByType text/html "access plus 30 days"

понятно означает, что кеш будет запрашивать свежий контент через 30 дней.

Тем не менее,

ExpiresByType text/html "modification plus 2 hours"

не имеет смысла.

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

Ответы [ 4 ]

36 голосов
/ 19 февраля 2009

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

Позвольте мне объяснить на примере: скажем, ваша конфигурация Apache включает в себя строку

ExpiresDefault modification plus 2 hours

и у вас есть файл index.html, к которому применяется директива ExpiresDefault, на сервере. Предположим, вы загрузили версию index.html в 9:53 по Гринвичу, перезаписав предыдущую существующую index.html (если она была). Так что теперь время модификации index.html составляет 9:53 по Гринвичу. Если вы выполняете ls -l на сервере (или dir в Windows), вы увидите это в листинге:

-rw-r--r--  1 apache apache    4096  Feb 18 09:53 index.html

Теперь, при каждом запросе, Apache отправляет заголовок Last-Modified с временем последнего изменения файла. Поскольку у вас есть эта директива ExpiresDefault, она также отправит заголовок Expires со временем, равным времени изменения файла (9:53) плюс два часа. Вот часть того, что видит браузер:

Last-Modified: Wed, 18 Feb 2009 09:53:00 GMT
Expires: Wed, 18 Feb 2009 11:53:00 GMT

Если время, в которое браузер делает этот запрос, - до 11:53 по Гринвичу, браузер будет кэшировать страницу, поскольку срок ее действия еще не истек. Таким образом, если пользователь сначала посещает страницу в 11:00 по Гринвичу, а затем снова переходит на ту же страницу в 11:30 по Гринвичу, браузер увидит, что его кэшированная версия все еще действительна и не будет (или, скорее, не может ) сделать новый HTTP-запрос.

Если пользователь заходит на страницу в третий раз в 12:00 по Гринвичу, браузер видит, что срок действия его кэшированной версии уже истек (после 11:53), поэтому он пытается проверить страницу, отправив запрос на сервер. с заголовком If-Modified-Since. Ответ 304 (без изменений) без тела будет возвращен, поскольку дата страницы не была изменена с момента ее первого показа. Поскольку срок действия истек - страница «устарела» - запрос на проверку будет выполняться при каждом последующем посещении страницы, пока проверка не завершится неудачей.

Теперь давайте представим, что вы загрузили новую версию страницы в 11:57. В этом случае попытка браузера проверить старую версию страницы в 12:00 не удалась, и в ответ вместе с новой страницей он получает два новых заголовка:

Last-Modified: Wed, 18 Feb 2009 11:57:00 GMT
Expires: Wed, 18 Feb 2009 13:57:00 GMT

(Время последней модификации файла становится 11:57 после загрузки новой версии, и Apache рассчитывает время истечения как 11:57 + 2:00 = 13:57 по Гринвичу.)

Проверка (с использованием более поздней даты) теперь не требуется до 13:57.

(обратите внимание, конечно, что многие другие вещи отправляются вместе с двумя заголовками, которые я перечислил выше, я просто обрезал все остальные для простоты)

3 голосов
/ 19 февраля 2009

Сервер отправляет заголовок, такой как: "Last-Modified: Wed, 18 Feb 2009 00:00:00 GMT". Кэш ведет себя на основе этого заголовка или времени доступа.

Скажите, если ожидается, что контент будет обновляться каждый день, то вы хотите, чтобы срок его действия истек "изменение плюс 24 часа".

Если вы не знаете, когда будет обновляться контент, лучше основывать его на времени доступа.

0 голосов
/ 10 октября 2014

Прежде всего, спасибо David Z за подробное объяснение выше. В ответ на вопрос бушмена о том, почему имеет смысл вызывать кеширование, если серверу все еще требуется сделать запрос, ответ заключается в том, что время, сэкономленное на том, что возвращает сервер, экономится. Если директивы кеша указывают, что содержимое файла все еще свежо, вместо возврата содержимого возвращается код 304 с пустым телом ответа. Вот где экономится время.

Лучшее объяснение, чем я дал, здесь, от https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers:

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

Время на основе

Условный запрос на основе времени гарантирует, что только если запрошенный ресурс изменился с момента кэширования копии браузера, содержимое будет передано. Если кэшированная копия является самой последней, сервер возвращает код ответа 304.

Чтобы включить условные запросы, приложение указывает время последнего изменения ресурса через заголовок ответа Last-Modified.

Cache-Control: общедоступный, max-age = 31536000 Дата последнего изменения: понедельник, 03 января 2011 г. 17:45:57 GMT

В следующий раз, когда браузер запрашивает этот ресурс, он будет запрашивать содержимое ресурса только в том случае, если они не изменились с этой даты, используя заголовок запроса If-Modified-Since

If-Modified-Since: понедельник, 3 января 2011 17:45:57 GMT

Если ресурс не изменился с понедельника, 3 января 2011 г. 17:45:57 GMT, сервер вернется с пустым телом с кодом ответа 304.

0 голосов
/ 19 февраля 2009

Насколько я понимаю, модификация просит браузер основывать время кеширования на основе значения последнего модифицированного заголовка HTTP. Таким образом, модификация плюс 2 часа будет временем последнего изменения + 2 часа.

...