Возможности HTTP/2 и их производительность в практических приложениях

внешний интерфейс сервер HTTP CSS

введение

HTTP/2 — это протокол HTTP нового поколения, официально выпущенный в 2015 году. Он стремится сократить воспринимаемую пользователем задержку и повысить эффективность передачи по сети на основе сохранения семантики HTTP1.x и сохранения сетевой инфраструктуры. В этой статье будут представлены четыре части: история HTTP, новые функции HTTP/2, методы обновления и анализ последствий. В основном он включает четыре вопроса о том, зачем нам нужен HTTP/2, что HTTP/2 может нам дать, как обновить и как текущий HTTP/2 работает в практических приложениях.

HTTP История

Прошло более 20 лет с тех пор, как Тим Бернерс-Ли предложил идею протокола HTTP в 1991 году, и развитие Интернета также меняется с каждым днем ​​в течение последних 20 лет. Чтобы удовлетворить потребности Интернета в разные эпохи, итерация обновления протокола HTTP прошла через несколько версий HTTP0.9, HTTP/1.0, HTTP/1.1, SPDY и HTTP/2. Ниже приводится краткое введение в эти версии HTTP.

HTTP 0.9 (1991 г.)

HTTP/0.9 возник в зачаточном состоянии веб-разработки и представляет собой HTTP-протокол, состоящий из одной строки запроса. HTTP/0.9 поддерживает только запросы GET POST HEAD без номера версии в строке запроса (а других версий в то время не было). Соединение закрывается после того, как сделан запрос и сервер отвечает (поддерживается только обычный текст, без заголовков ответа). Популярные веб-серверы по-прежнему поддерживают HTTP/0.9, потому что его поддержка не требует больших затрат.

GET /index
(响应)
(连接关闭)

HTTP/1.0

С 1991 по 1995 год, с появлением веб-браузеров, у людей возникало все больше и больше потребностей в веб-страницах.Наиболее типичным примером является то, что людей больше не удовлетворяют гипертекстовые документы, которые содержат только текст и гиперссылки, но должны иметь возможность отображать текст., стили, изображения и другие мультимедийные типы данных. Таким образом, простой транспортный протокол HTTP/0.9 быстро стал нежизнеспособным. В 1996 году HTTP-WG опубликовала RFC1945, описывающую основные возможности HTTP/1.0:

  • Запросы и ответы имеют несколько заголовков, а строка запроса содержит версию протокола.
  • Содержит строку ответа, в основном включая версию протокола и статус ответа.
  • Content-Type включен в заголовок ответа, который может поддерживать несколько типов содержимого влияния.
  • После каждого ответа на запрос соединение закрывается

На самом деле, отныне протокол HTTP содержит больше того, на что указывает его название (Hypertext Transfer), но это имя все еще используется.

/* 请求 */
GET /rfc/rfc1945.txt HTTP/1.0
User-Agent: CERN-LineMode/2.15 libwww/2.17b3 Accept: */* /* 响应 */
HTTP/1.0 200 OK
ontent-Type: text/plain
Content-Length: 137582
Expires: Thu, 01 Dec 1997 16:00:00 GMT Last-Modified: Wed, 1 May 1996 12:45:26 GMT Server: Apache 0.84

HTTP/1.1

RFC2068, определяющий HTTP/1.1, был официально выпущен в 1997 году, за ним последовали улучшения и обновления HTTP/1.1 в RFC2616, выпущенном в 1999 году. В общем, HTTP/1.1 в основном проясняет моменты двусмысленности в HTTP/1.0 ранее и добавляет много новых возможностей на этой основе:

  • постоянная передача
  • Передача фрагментированного кодирования
  • запрос диапазона байтов
  • кодирование передачи
  • Усовершенствованный механизм кэширования
  • Запросы конвейера
// 请求1
GET /index.html HTTP/1.1
Host: website.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4)... (snip)

// 响应1
HTTP/1.1 200 OK
Server: nginx/1.0.11
Accept-Ranges: bytes // 如果不为none,代表server支持范围请求
Connection: keep-alive // 持久传输,本次请求响应结束后不关闭连接
Content-Type: text/html; charset=utf-8
Cache-Control: max-age=0, no-cache // 缓存控制
Transfer-Encoding: chunked // 传输编码

100 // 当前响应块大小(256Bytes)
<!doctype html> ... (snip) // 响应内容

100 // 另一块(256Bytes)
... (snip) // 响应内容

0 // 响应分块结束

// 请求2
GET /favicon.ico HTTP/1.1 // 上次请求未关闭连接,本次重用该连接
Range: bytes=0-1023 // 请求字节范围
Connection: close // 告知服务器本次请求响应后关闭连接

// 响应2
HTTP/1.1 200 OK // 第二次请求的响应行
Content-Range: bytes 0-1023/146515 // 响应字节范围//整体字节数
Connection: close // 告知浏览器响应完成或关闭该连接

SPDY & HTTP/2

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

  • Блокировка заголовка: в HTTP/1.1 текущее соединение может быть повторно использовано только для отправки следующего запроса после ответа на запрос.Даже если технология конвейера позволяет отправить следующий запрос до того, как текущий ответ будет завершен, ответ все еще возвращаются в строгом порядке, то есть если предыдущий А-ответ заблокирован, а последующие ответы не придут.
  • Повторная передача несжатых данных заголовка: начиная с HTTP/1.0, HTTP-запросы обычно содержат большое количество закодированных ASCII заголовков. Большинство этих заголовков обычно не меняются и переносятся с каждым запросом, который уже переполнен. Невыносимая сеть приносит больше давление (особенно длинные поля заголовка, такие как User Agent и Cookie).

В 2009 году Google предложил экспериментальный протокол SPDY (произносится как «скорый»), целью которого является повышение скорости загрузки страниц без изменения текущей реализации веб-сайта. После того, как был предложен SPDY, основные браузеры, такие как Chrome, Firefox и Opera, последовательно предоставили реализации, а многие крупные веб-сайты (такие как Google, Twitter, Facebook и т. д.) соответственно предоставили свои реализации сеансов SPDY. В 2012 г. HTTP-WG предложила проект построения HTTP/2 на основе SPDY.В 2013 г. была дана первая реализация HTTP/2.С тех пор HTTP/2 и SPDY развивались параллельно, на клиенте и сервер.Было проведено всестороннее и надежное тестирование. В 2015 году Google объявил, что прекратит дальнейшую поддержку SPDY, отметив тем самым официальный выход HTTP/2 на сцену истории.

Что нового в HTTP/2

Уровень двоичных кадров и мультиплексирование

В отличие от HTTP/1.x, который использует код ASCII для передачи открытого текста, HTTP/2 использует двоичную форму с более высокой эффективностью передачи между сервером и клиентом. Стоит отметить, что двоичный фрейм сообщения в HTTP/2 делится на фрейм заголовка (Header Frame) и фрейм данных (Data Frame), главным образом потому, что HTTP/2 предоставляет отдельный метод сжатия для поля заголовка. который может минимизировать данные заголовка, передаваемые в сети (см. следующий раздел).В HTTP/2 передачу всех данных можно разделить на три уровня: Connection, Stream и Frame. В отличие от параллельных соединений, используемых в HTTP/1.1, HTTP/2 повторно использует одно соединение для всего сеанса клиента и сервера. Набор полных запросов и ответов в этом соединении называется потоком. Каждая часть данных (заголовок, сегмент данных) в потоке называется кадром. Кадр — это наименьшая единица связи в HTTP/2, которая содержит «идентификационную» информацию о том, к какому потоку он принадлежит.В HTTP/1.x запросы и ответы обычно отправляются параллельно, поддерживая несколько соединений.Из-за ограничения вычислительных ресурсов и ресурсов хранения блокировка заголовков не может быть полностью решена путем открытия новых соединений на неопределенный срок (обычно верхний предел равен шести). вопрос. В HTTP/2 вся передача данных осуществляется в одном соединении. Каждый фрейм данных может быть отправлен после того, как отправитель будет готов, не дожидаясь ответа на предыдущий запрос. После приема кадров данных, отправленных не по порядку, сторона, принимающая данные, повторно собирает данные в соответствии с «идентификацией», содержащейся в каждом кадре, для получения полных данных запроса или ответа. Технология мультиплексирования, используемая в HTTP/2, полностью решает проблему блокировки заголовков, она повторно использует сетевые ресурсы соединения между каждой группой запросов и ответов, что одновременно снижает накладные расходы на ресурсы и задержку передачи данных.

Сжатие заголовков (Hpack)

Как упоминалось ранее, HTTP/1.x постоянно содержит нечасто изменяющиеся длинные заголовки в запросах и ответах, что излишне нагружает сеть. Помимо преобразования открытого текста ASCII в двоичные кадры для повышения эффективности передачи по сети, HTTP/2 также предлагает специальную схему сжатия данных заголовка пакета — Hpack. Основная идея состоит в том, чтобы уменьшить размер поля заголовка в сообщении, повторно используя заголовок в предыдущем запросе, отправленном в текущем соединении, и отправлять только недавно добавленную или измененную информацию заголовка. Процесс сжатия заголовка показан на следующем рисунке:

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

приоритет потока

В HTTP/2 запросы и ответы могут передаваться не по порядку, поэтому нам нужен механизм, гарантирующий, что другие данные ответа зависят от ключевых ресурсов или передаются в первую очередь, чтобы рендеринг и использование веб-страниц были максимально удобными. На уровне потока в HTTP/2 используется «дерево приоритетов», чтобы гарантировать, что данные ответа могут быть переданы в соответствии с зависимостями и порядком приоритета.

«Дерево приоритетов» можно представить, как показано на следующем рисунке. Ответ потока, представленный дочерним узлом, зависит от потока родительского узла, поэтому поток родительского узла должен быть передан первым. Среди одноуровневых узлов точкам с большими весами следует выделять больше сетевых ресурсов и передавать их предпочтительно. В «дереве приоритетов», показанном в (3) на рисунке ниже, A и B зависят от C, а C зависит от D, поэтому D должен быть передан первым, а C должен быть передан после передачи D. Аналогично, после C передается Только сетевые ресурсы, занятые данными A, B, A и B, должны соответствовать соотношению 3:1 в процессе передачи.

Server Push

Проще говоря, Server Push позволяет серверу отвечать на запросы, которые еще не были выданы. Как показано на рисунке ниже, в первом запросе клиент делает запрос на index.html. Благодаря анализу Index.html сервер может сделать вывод о том, что стиль.css и script.js также требуются для загрузки этого HTML, поэтому эти содержимое могут быть отправлены вместе в ответ первого запроса, избегая следующих двух Задержка (RTT, время турнира), вызванная запросом и ответом. Хотя использование встроенного в HTTP / 1.x также может достичь аналогичного эффекта на серверный толчок, встроенный в Inline имеет следующие недостатки:

  • Нет отдельного кеша для CSS или JS. Если метод кэширования HTML не соответствует встроенному контенту, когда страница доступна позже, кэшированные CSS или содержимое JS будут неоднократно запрошены нагрузку.
  • Другие страницы, использующие этот стиль, будут загружаться повторными запросами.

Обновление до HTTP/2

Перед обновлением сначала убедитесь, что ваш текущий клиент (браузер) и сервер поддерживают HTTP/2. К счастью, до сих пор большинство браузеров обеспечивали поддержку сеансов HTTP/2, а последние версии основных веб-серверов уже могут поддерживать HTTP/2 (Nginx ^ 1.9.5, Apache ^ 2.4.24 mod_http2) . Таким образом, вам нужно только установить последнюю версию сервера, чтобы использовать новые функции HTTP/2, которые он предоставляет. Следует отметить, что перед обновлением HTTP/2 убедитесь, что сервер поддерживает SSL (поддерживает HTTPS). HTTP/2 сам по себе не требует базовой поддержки SSL, но почти все браузеры игнорируют соединения HTTP/2, когда сервер не поддерживает SSL.

Удалены некоторые оптимизации для HTTP/1.x.

В HTTP/1.x есть некоторые «хитрости и хитрости» для улучшения веб-производительности, но эти методы могут иметь противоположный эффект в HTTP/2, поэтому наш первый шаг — удалить их, которые могут снизить производительность в первую очередь. Оптимизация.

Шардинг домена

В HTTP / 1.x на обоих концах общения имеются большинство шести соединений, и они поддерживаются и управляются различными доменными именами. Для того, чтобы пробить это ограничение, запрошенные ресурсы обычно размещаются под разными доменными именами (например,shard1.example.org, shard2.example.org). В HTTP/2, поскольку нет необходимости открывать новые соединения для решения проблемы блокировки заголовков, нет необходимости увеличивать количество коммуникационных соединений таким образом. И наоборот, использование сегментирования доменных имен в HTTP/2 вызовет следующие две проблемы:

  • Увеличьте время разрешения доменного имени DNS
  • Увеличьте размер сжатого заголовка при передаче. Как упоминалось выше, мультиплексирование данных при сжатии заголовков поддерживается на одном соединении, а вновь открытое соединение после фрагментации доменного имени не может повторно использовать данные заголовка, которые были отправлены ранее, что приводит к некоторым ненужным данным при передаче по сети.

Спрайт

В HTTP/1.x, чтобы уменьшить проблему блокировки заголовков, вызванную запросом нескольких изображений, несколько изображений обычно объединяются в большое изображение, а затем все изображения загружаются в браузер в одном запросе, а затем все изображения загружаются с использованием технологии CSS, требуемые части отображаются по мере необходимости. Очевидно, что карта спрайтов принесет следующие проблемы:

  • Чтобы увеличить количество кода, вам нужно написать какой-то ненужный код CSS.
  • Во время рендеринга браузера в память необходимо загрузить больше содержимого изображения.

Сшивание JavaScript CSS

Подобно принципу Sprite, метод объединения JavaScript и CSS также заключается в уменьшении количества запросов, чтобы избежать потенциальных проблем с блокировкой заголовков. В HTTP/2, поскольку нет проблемы блокировки заголовков, следует избегать некоторой ненужной загрузки ресурсов, вызванной этой оптимизацией.

Обновить

В зависимости от типа бизнеса и сложности вы можете выбрать различные методы обновления. Вот три метода обновления HTTP/2.

Храните статические ресурсы в CDN, поддерживающей HTTP/2.

Обычно подавляющее большинство запросов на веб-сайте инициируются для статических ресурсов, поэтому развертывание статических ресурсов в CDN, поддерживающей HTTP/2, является наиболее удобным и быстрым методом обновления. В этом случае запросы на доступ к статическим ресурсам выполняются через HTTP/2, а доступ к API осуществляется через HTTP/1.x. Хотя этот метод более удобен, часто бывает сложно в полной мере воспользоваться всеми реализованными новыми функциями (такими как Server Push, управление приоритетами и т. д.) из-за потери контроля над поддержкой HTTP/2 на сервере. сторона.

Обновите обратный прокси-сервер

Обратный прокси-сервер расположен между клиентом и реальным сервером и используется для балансировки нагрузки на серверы с большим одновременным доступом. В этом случае блокировка заголовков в основном происходит при обмене данными между клиентом и прокси-сервером, поэтому поддержка HTTP/2 на прокси-сервере может устранить большинство проблем с производительностью, вызванных блокировкой заголовков. Прокси-сервер и реальный сервер по-прежнему используют HTTP/1.x для связи.

Сервер полностью обновлен

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

анализ случая

case1

Акамай даеттестовая страницаИспользуется для сравнения огромной разницы в производительности между HTTP/2 и HTTP/1.x при наличии большого количества запросов. Глядя на водопадный поток запросов HTTP/2 и HTTP/1.x, можно обнаружить, что существует серьезная проблема блокировки заголовков в соединениях HTTP/1.x, и не более 6 запросов могут быть выполнены на 6 соединениях. одновременно, в то время как HTTP/2 использует механизм мультиплексирования одного соединения для нескольких запросов.Количество запросов, которые могут быть получены одновременно, не ограничивается количеством соединений, и пропускная способность сети может использоваться более полно. В авторском сетевом окружении последнее позволяет сократить время загрузки одного и того же ресурса в 50 раз. Хотя это крайний случай, улучшения производительности, обеспечиваемые HTTP/2, очевидны.

case2

Dropbox предлагает обновление своего веб-сервера с SPDY до HTTP/2 (Niginx 1.9.15).Процесс и анализ. На рисунке ниже показана доля соединений SPDY и соединений HTTP/2 в процессе обновления.Видно, что процесс обновления постепенно завершается на нескольких серверах, что дает нам хорошее сравнение производительности до и после обновления. Хороший материал.На рисунке ниже показано соотношение пропускной способности сети, занимаемой запросами (вход) и ответами (исход) в процессе обновления, по отношению к среднему значению до обновления. Видно, что после переключения пропускная способность сети, занимаемая запросом, значительно снизилась (примерно наполовину от исходной), что в основном вызвано сжатием заголовков HTTP/2 (хотя SPDY также предоставляет функцию сжатия заголовков, но обычно не включен из соображений безопасности). Сетевые ресурсы, занятые ответом, не сильно изменились, в основном потому, что данные заголовка составляли лишь небольшую часть ответа.При обновлении также были обнаружены некоторые существующие проблемы. Из рисунка ниже видно, что для POST-запросов средняя задержка увеличилась на 50%. Это связано с недостатком в поддержке Nginx 1.9.15 HTTP/2. В частности, Nginx будетSETTINGS.INITIAL_WINDOW_SIZEПоле установлено в 0, что означает, что запрос POST не отправляет данные сразу после завершения рукопожатия TCP, а требует, чтобы RTT ждал, пока сервер увеличит значение до большего значения, прежде чем начать отправку данных (см.Механизм медленного запуска TCP). Хотя Nginx 1.11.0 устраняет эту проблему, он по-прежнему напоминает нам о том, что перед обновлением HTTP/2 нам необходимо полностью изучить текущие проблемы используемого сервера и соответствующего пакета, чтобы избежать возможного снижения производительности, вызванного обновлением.

case3

На веб-сайте 99design также подробно описан переход на HTTP/2.Суммировать. Работа по миграции в основном реализуется путем развертывания ресурсов изображения в CDN, поддерживающей HTTP/2 (метод обновления 1).Показатель производительности — время визуального рендеринга страницы. При тестировании разных страниц можно обнаружить следующие три явления (о разнице между ограничением задержки и ограничением пропускной способности см.здесь):

  • В сценариях с ограниченной задержкой скорость визуального рендеринга обновленной страницы увеличивается примерно на 5%.
  • В сценариях с ограниченной пропускной способностью скорость визуального рендеринга обновленной страницы будет снижена на 15%.
  • В сценариях, где пропускная способность и задержка ограничены, скорость визуального рендеринга обновленной страницы будет дополнительно снижена, даже достигая более 25% (первое изображение ниже — http/1.1, а второе изображение — HTTP/2).

Согласно анализу, причина падения производительности заключается в том, что интерфейсный код теряет контроль над приоритетом загрузки ресурсов после обновления HTTP/2, что приводит к тому, что некоторые ключевые ресурсы, влияющие на визуальный рендеринг, загружаются позже, что приводит к увеличению всего времени визуального рендеринга. В частности, в HTTP/1.x ресурс, который первым инициирует запрос, обычно загружается первым. Таким образом, мы можем контролировать приоритет загрузки ресурсов на внешнем интерфейсе и загружать ресурсы, которые более важны для визуального представления, в первую очередь. Но в HTTP/2 ответ возвращается не по порядку, и некоторые некритические ресурсы могут быть возвращены первыми. Естественно, это не проблема, если полоса пропускания не является ограничивающим фактором. Но когда эти некритические ресурсы исчерпывают полосу пропускания, критическим ресурсам приходится ждать освобождения полосы пропускания, прежде чем возвращаться. Короче говоря, использование HTTP/2 переместило контроль над порядком загрузки ресурсов с внешнего интерфейса на внутренний. Очевидно, что CDN, который он использует, не поддерживает приоритетную передачу потоков. Это также подтверждает, что, как упоминалось выше, использование CDN для обновления HTTP/2 может лишить нас возможности использовать некоторые функции HTTP/2 или даже полностью выйти из-под контроля.

Суммировать

Наконец, подведем итоги.

Зачем использовать HTTP/2?

Проблема блокировки заголовков в HTTP/1.x приводит к тому, что соединение всегда ожидает ответа, не используя полностью пропускную способность; HTTP/1.x передает большое количество повторяющихся заголовков запросов в сети, что составляет большую часть сетевая нагрузка Объем данных, которые необходимо передать.

Что нам может дать HTTP/2?

В дополнение к решению вышеуказанных проблем HTTP/1.x, новый протокол также включает новые функции, такие как Server Push и передача с приоритетом потока, что еще больше повышает производительность.

Как обновить?

Все текущие основные браузеры поддерживаются, поэтому, как правило, требуется только обновление сервера. Три варианта: найти CDN с поддержкой HTTP/2 для развертывания статических ресурсов на веб-сайте, обновить прокси-сервер, обновить все серверы.

Как на самом деле ведет себя HTTP/2?

В среде с большим количеством запросов и ограниченной задержкой производительность HTTP/2 имеет очевидные преимущества перед HTTP/1.x. Однако, учитывая, что HTTP/2 еще молод, многие функции реализованы не полностью, и многие функции могут работать не очень хорошо. Поэтому перед оперативным обновлением проведите достаточное тестирование, чтобы убедиться, что используемая вами реализация поддерживает необходимые вам функции и что ее ошибки не оказывают существенного влияния на производительность.

【использованная литература】