Когда веб-серверы отправляют страницу, почему они не отправляют все необходимые CSS, JS и изображения без запроса?

Когда веб-страница содержит один файл CSS и изображение, почему браузеры и серверы тратят время на этот традиционный отнимающий много времени маршрут:

  1. браузер отправляет исходный запрос GET для веб-страницы и ожидает ответа сервера.
  2. браузер отправляет другой запрос GET для файла css и ожидает ответа сервера.
  3. браузер отправляет другой запрос GET для файла изображения и ждет ответа сервера.

Вместо этого они могли бы использовать этот короткий, прямой, экономящий время маршрут?

  1. Браузер отправляет запрос GET для веб-страницы.
  2. Веб-сервер отвечает ( index.html , а затем style.css и image.jpg )
43 голоса | спросил Ahmed 16 +04002014-10-16T21:01:04+04:00312014bEurope/MoscowThu, 16 Oct 2014 21:01:04 +0400 2014, 21:01:04

6 ответов


61

Короткий ответ: «Потому что HTTP не был предназначен для этого».

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

  • Не было версии протокола, просто запрос на ресурс
  • Не было заголовков
  • Для каждого запроса требуется новое TCP-соединение.
  • Не было сжатия

Протокол был впоследствии пересмотрен для решения многих из этих проблем:

  • Запросы были версиями, теперь запросы выглядят как GET /foo.html HTTP /1.1
  • Заголовки были добавлены для метаинформации с запросом и ответом
  • Связи разрешалось повторно использовать с помощью Connection: keep-alive
  • Были введены фрагментированные ответы, позволяющие повторно использовать соединения, даже когда размер документа неизвестен заранее.
  • Было добавлено сжатие Gzip.

В этот момент HTTP был взят как можно дальше, не нарушая обратной совместимости.

Вы не первый, кто предположил, что страница и все ее ресурсы должны быть перенаправлены клиенту. Фактически, Google разработал протокол, который может сделать так называемый SPDY .

Сегодня и Chrome, и Firefox могут использовать SPDY вместо HTTP для серверов, которые его поддерживают. С веб-сайта SPDY его основными функциями по сравнению с HTTP являются:

  
  • SPDY позволяет клиенту и серверу сжимать заголовки запросов и ответов, что сокращает использование полосы пропускания, когда похожие заголовки (например, файлы cookie) отправляются многократно для нескольких запросов.
  •   
  • SPDY позволяет выполнять множественные, одновременно мультиплексированные запросы по одному соединению, экономить на взаимных поездках между клиентом и сервером и предотвращать блокирование низкоприоритетных ресурсов более приоритетными запросами.
  •   
  • SPDY позволяет серверу активно продвигать ресурсы клиенту, чтобы он знал, что клиент будет нужен (например, файлы JavaScript и CSS), не дожидаясь, пока клиент запросит их, что позволит серверу эффективно использовать неиспользуемую пропускную способность.
  •   

Если вы хотите обслуживать свой сайт с помощью SPDY для браузеров, которые его поддерживают, вы можете сделать это. Например Apache имеет mod_spdy .

SPDY стала основой HTTP версии 2 с технологией push-сервера.

ответил Stephen Ostermiller 16 +04002014-10-16T21:47:55+04:00312014bEurope/MoscowThu, 16 Oct 2014 21:47:55 +0400 2014, 21:47:55
13

Ваш веб-браузер не знает о дополнительных ресурсах, пока он не загрузит веб-страницу (HTML) с сервера, которая содержит ссылки на эти ресурсы.

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

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

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

Веб-браузер обычно может выполнять два HTTP-запроса параллельно. Это не похоже на AJAX - это оба асинхронных метода для загрузки веб-страниц - асинхронная загрузка файлов и загрузка асинхронного контента. С keep-alive мы можем сделать несколько запросов с использованием одного соединения, а при конвейеризации мы можем сделать несколько запросов, не дожидаясь ответов. Обе эти технологии очень быстры, потому что большинство служебных сообщений обычно происходит от открытия /закрытия TCP-соединений:

keep-alive

pipelining

Немного истории в Интернете ...

Веб-страницы начинаются как текстовые сообщения электронной почты, а компьютерные системы разрабатываются вокруг этой идеи, образуя некоторую свободную для всех коммуникационную платформу; В то время веб-серверы все еще были собственностью. Позже в «спецификацию электронной почты» были добавлены дополнительные слои в виде дополнительных типов MIME, таких как изображения, стили, сценарии и т. Д. В конце концов, MIME означает многоцелевое интернет-расширение Mail . Рано или поздно у нас было то, что по существу мультимедийное почтовое сообщение, стандартизированные веб-серверы и веб-страницы.

  

HTTP требует, чтобы данные передавались в контексте электронной почты   сообщений, хотя данные чаще всего не являются электронной почтой.

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

Источник: я разработал веб-сервер на основе событий, такой как Node.js. Он называется Rapid Server .

Литература:

Дальнейшее чтение:

ответил perry 17 +04002014-10-17T20:25:46+04:00312014bEurope/MoscowFri, 17 Oct 2014 20:25:46 +0400 2014, 20:25:46
12

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

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

ответил John Conde 16 +04002014-10-16T21:25:56+04:00312014bEurope/MoscowThu, 16 Oct 2014 21:25:56 +0400 2014, 21:25:56
8

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

Теперь вы можете попытаться обойти эту трату пропускной способности, сказав « ОК, но клиент может указать, что у нее уже есть некоторые из этих ресурсов, поэтому сервер больше не будет отправлять ее ». Что-то вроде:

GET /index.html HTTP /1.1
Хост: www.example.com
If-None-Match: "686897696a7c876b7e"
Подключение: Keep-Alive

GET /style.css HTTP /1.1
Хост: www.example.com
Если-Нет-Матч: "70b26618ce2c246c71"

GET /image.png HTTP /1.1
Хост: www.example.com
Если-Нет-Матч: "16d5b7c2e50e571a46"

И затем получите только файлы, которые не изменились, отправляются по одному TCP-соединению (с использованием HTTP-конвейерной обработки по постоянному соединению). И угадай что? Как работает уже (вы также можете использовать If-Modified-Since вместо If-None-Match ).


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

Для этого вам не нужно иметь CSS или JavaScript в отдельном файле, вы можете включить их в основной файл HTML, используя <style> и <script> (вам, вероятно, даже не нужно делать это вручную, возможно, ваш механизм шаблонов может сделать это автоматически). Вы даже можете включать изображения в файл HTML, используя URI данных , например:

<img src = "data: image /png; base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4 //8 /w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg ==" alt = "Red dot" />

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

Теперь, если вы действительно заботитесь, вы даже можете сделать ваши веб-скрипты достаточно умными, чтобы получить лучшее из обоих миров: при первом запросе (у пользователя нет файла cookie), отправить все (CSS, JavaScript, изображения), встроенные только в один HTML-файл, как описано выше, добавьте ссылку rel = "prefetch" теги для внешних копий файлов и добавить файл cookie. Если у пользователя уже есть файл cookie (например, он посетил ранее), отправьте ему обычный HTML-код с кодом <img src = "example.jpg">, <link rel = "stylesheet" type = "text /css" href = "style.css"> и т. д.

Таким образом, при первом посещении браузер запрашивает только один HTML-файл и получает и показывает все. Затем он (в режиме ожидания) предварительно загружал внешние CSS, JS, изображения. При следующем посещении браузером браузер запрашивает и получает только измененные ресурсы (возможно, только новый HTML).

Дополнительные данные изображений CSS + JS + будут отправляться дважды, даже если вы нажмете сотни раз на веб-сайте. Гораздо лучше, чем сотни раз, как предлагалось предлагаемое решение. И никогда (в первый раз, а не в следующий раз) не будет больше одного увеличения времени ожидания.

Теперь, если это звучит слишком много, и вы не хотите идти с другим протоколом, например SPDY , для Apache уже есть такие модули, как mod_pagespeed , который может автоматически выполните некоторые из этих работ для вас (слияние нескольких файлов CSS /JS в один, автоматическое вложение небольшого CSS и их минифинирование, создание небольших замещающих изображений, ожидающих загрузки оригиналов, ленивые загрузки изображений и т. д.), не требуя, чтобы вы изменяли один линии вашей веб-страницы.

ответил Matija Nalis 19 +04002014-10-19T16:40:56+04:00312014bEurope/MoscowSun, 19 Oct 2014 16:40:56 +0400 2014, 16:40:56
6

HTTP2 основан на SPDY и делает именно то, что вы предлагаете:

  

На высоком уровне HTTP /2:

     
  • является двоичным, вместо текстового
  •   
  • полностью мультиплексируется вместо упорядоченного и блокирующего
  •   
  • может поэтому использовать одно соединение для параллелизма
  •   
  • использует сжатие заголовка для уменьшения служебных данных
  •   
  • позволяет серверам получать «пустые» ответы в кэши клиента
  •   

Дополнительно доступно HTTP 2 Faq

ответил MaBu 17 +04002014-10-17T03:01:51+04:00312014bEurope/MoscowFri, 17 Oct 2014 03:01:51 +0400 2014, 03:01:51
3

Потому что он не предполагает, что эти вещи действительно необходимы .

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

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

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

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

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

ответил The Spooniest 17 +04002014-10-17T17:03:47+04:00312014bEurope/MoscowFri, 17 Oct 2014 17:03:47 +0400 2014, 17:03:47

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132