Назад | Перейти на главную страницу

Как веб-сервер / протокол http обрабатывают контроль версий и сжатие?

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

Затем, если на сервере включено сжатие, такое как gzip, файлы, которые должны быть предоставлены клиенту, должны быть сжаты с помощью gzip, что потребует некоторой обработки на стороне сервера.

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

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

Но это только предположение с точки зрения программирования, и я точно не знаю.

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

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

  1. В браузере есть локальная (кэшированная) версия файла, которая помечена как истекающая через определенное время, и это время находится в будущем. В этом случае у браузера есть выбор: либо использовать кэшированную версию как есть, либо он может отправить запрос на сервер, чтобы узнать, изменился ли файл. Если браузер отправит запрос, он будет включать If-Modified-Since заголовок, содержащий время последнего обращения к файлу.
  2. В браузере есть кешированная версия файла, срок действия которой уже истек. В этом случае браузер обязательно отправит запрос на сервер, чтобы узнать, есть ли новая версия, и этот запрос (обычно) будет включать If-Modified-Since заголовок, содержащий время последнего обращения к файлу.
  3. Браузер вообще не кэширует файл, и в этом случае он отправляет запрос без If-Modified-Since заголовок.

Когда запрос попадает на сервер, в основном может произойти пара вещей. Если запрос не включать If-Modified-Since заголовок, сервер продолжит и отправит файл обратно, используя код ответа HTTP 200 (OK). (Или он отправит 404 File Not Found, или 403 Forbidden, или что-то еще). Но если запрос сделал включать If-Modified-Since заголовок, сервер знает, что он должен отправить обратно файл только в том случае, если он был изменен с момента времени, указанного в заголовке. Теперь, если файл был изменен с того времени, сервер снова отправит файл с кодом 200 или 403, 404, как угодно. Но если в файле не был изменен с указанного времени - что, помните, означает, что кешированная версия браузера все еще актуальна - сервер может ответить кодом 304 (Not Modified) и пропустить содержимое самого файла. Это экономит некоторое количество сетевого трафика.

Теперь, предполагая, что сервер собирается ответить полным содержимым файла, есть несколько способов сделать это, в зависимости от того, как сервер написан и / или настроен. Очевидно, он может просто читать файл с диска (или запускать программу для его генерации, если это динамическая страница) каждый раз, когда приходит запрос, и просто отправлять его обратно, но, как вы знаете, это неэффективно. Одна вещь, которую может сделать сервер, - это отправить обратно сжатую версию файла, если браузер указывает Accept-Encoding: gzip в своем запросе. Для сервера действительно имеет смысл хранить кэшированную версию gzip-файла, и Apache (и, вероятно, большинство других серверов) можно настроить для этого. Когда сервер готовится отправить ответ, сжатый с помощью gzip, он проверяет время модификации кэшированной с помощью gzip версии по времени изменения исходного файла, и, если исходный файл был обновлен, он снова запустит gzip для него и заменит файл старая версия в кеше с новой версией.

Иногда серверы также могут кэшировать файлы в ОЗУ, если они часто запрашиваются. Я думаю, что Apache можно настроить для этого, но я не уверен. (Как вы уже, наверное, догадались, в Apache все дело в конфигурации.)

Что касается вашего вопроса о том, как запрашиваются файлы, браузер действительно запрашивает файлы по одному. Каждая страница HTML, файл CSS, файл Javascript, файл изображения и т. Д. Соответствует одному индивидуальному HTTP-запросу. Инструмент вроде Wireshark может фактически показать вам отдельные HTTP-запросы и ответы, поступающие на ваш компьютер и с вашего компьютера, если вам интересно. Но для экономии ресурсов соединение TCP / IP обычно остается открытым в течение всего набора запросов. Так, например, если у вас есть веб-страница с 3 изображениями и таблицей стилей CSS, вы, вероятно, получите такую ​​последовательность:

  • Браузер открывает соединение
  • Сервер подтверждает соединение
  • Браузер запрашивает HTML-страницу
  • Сервер отправляет HTML-страницу
  • Браузер запрашивает таблицу стилей CSS
  • Сервер отправляет таблицу стилей CSS
  • Браузер запрашивает изображение 1
  • Сервер отправляет изображение 1
  • Браузер запрашивает изображение 2
  • Сервер отправляет изображение 2
  • Браузер запрашивает изображение 3 с Connection: close заголовок
  • Сервер отправляет изображение 3
  • Сервер закрывает соединение

В Connection: close Заголовок может быть отправлен любой стороной, чтобы указать, что соединение TCP / IP должно быть закрыто после завершения этого запроса.

Надеюсь, это в основном касается того, о чем вы спрашивали, но спецификация HTTP - это ОГРОМНЫЙ документ, и есть много тонкостей, которые я упустил. На самом деле я нахожу это умеренно интересным чтением, поэтому я предлагаю вам взглянуть на него (опять же, я, вероятно, немного странный).