HTTP (HyperText Transfer Protocol — протокол передачи гипертекста) — сетевой протокол прикладного уровня, определяющий, как контент передаётся по сети. HTTP/2 — его последняя версия на момент выхода этой публикации.
Описание первой версии протокола, HTTP/0.9, было опубликовано ещё в 1991 году. В 1996-м появился HTTP/1.0. А предшественник HTTP/2 — HTTP/1.1 — вышел в 1999-м. После этого долго не было никаких обновлений.
Альтернативу HTTP/1.1 разработали в 2009 году. Это был протокол SPDY. Уже тогда у разработчиков было понимание, что существующая версия не обеспечивает достаточной скорости передачи данных. Целью инженеров было модифицировать способы приёма и отправки запросов и за счёт этого ускорить работу интернета. Именно этот протокол и лёг в основу HTTP/2.
SPDY действительно ускорял веб-приложения, поэтому набирал популярность и составлял серьёзную конкуренцию HTTP. В итоге разработчики решили, что в сети не должно быть двух конкурирующих протоколов, и объединили два этих стандарта. За создание нового протокола взялась рабочая группа HyperText Transfer Protocol из Инженерного совета Интернета. Так в 2015 году появился HTTP/2.
Основной целью новой версии было ускорение передачи данных. Вместе с этим разработчики хотели избавиться от «узких мест» HTTP/1.1, сделать его более производительным и безопасным.
Как мы уже сказали, эта версия протокола вышла в 1999 году. HTTP/2 появился только через 16 лет. За это время в интернете многое изменилось, у сайтов появились новые элементы: скрипты JаvaScript, анимация, стили CSS и много чего ещё.
Чтобы веб-ресурсы загружались достаточно быстро, запросы на разные элементы нужно было обрабатывать одновременно. Протоколу приходилось создавать сразу несколько TCP-соединений для передачи разных типов данных.
Это создавало колоссальную нагрузку на сеть.
При этом количество установленных соединений было ограничено, и их часто было недостаточно. Чтобы обойти ограничения, веб-разработчики использовали множество разных трюков, таких как доменный шардинг (использование поддоменов для загрузки ресурсов), объединение картинок в один файл и так далее. Это создавало дополнительные сложности.
Кроме того, так как HTTP/1.1 существовал уже много лет, в какой-то момент он перестал отвечать требованиям безопасности. Злоумышленники нашли в нём лазейки, позволяющие воровать данные пользователей.
HTTP/2 решил все эти проблемы и помог значительно ускорить передачу данных в интернете.
Чтобы устранить все проблемы, которые были у HTTP/1.1, разработчики внесли в новую версию ряд важных изменений. Мы не будем рассматривать все отличия, поговорим лишь о тех, которые непосредственно влияют на скорость.
Предыдущие версии HTTP передавали данные в текстовом формате. Это было удобно для пользователей. Но с технической точки зрения текстовые сообщения обрабатываются медленнее, чем бинарные.
В HTTP/2 сообщения состоят из фреймов — бинарных частей данных. Их совокупность называется потоком (stream). Каждый фрейм содержит в себе уникальный идентификатор потока — данные о том, к какому потоку он относится.
Существует несколько типов фреймов. Например, для передачи метаданных (размера сообщения, типа данных, адресов отправителя и получателя и так далее) используется фрейм HEADERS, для основного сообщения — фрейм DATA.
Есть фрейм RST_STREAM — он используется для прерывания потока. Клиент передаёт его серверу, чтобы сообщить, что этот поток ему больше не нужен. За счёт этого передача данных останавливается, но соединение остаётся открытым. Для сравнения: в HTTP/1.1 единственным способом прекратить передачу данных был разрыв соединения, а потом его приходилось открывать по новой.
Такой принцип работы бинарного протокола повышает качество соединения:
Кроме того, бинарная природа HTTP/2 открывает целый ряд возможностей для ускорения передачи данных, о которых мы сейчас и поговорим.
Это одно из главных отличий HTTP/2 от предыдущих версий. Именно благодаря этой особенности удалось увеличить скорость передачи данных.
В HTTP/1.1. для быстрой передачи разных типов данных создавалось несколько параллельных TCP-соединений. В новой версии все данные могут передаваться с помощью одного соединения.
Бинарный характер протокола даёт возможность параллельно загружать разную информацию без задержек, не блокируя ни один из ответов или запросов.
Потребность устанавливать только одно соединение сильно сокращает время на доставку контента. Дело в том, что для установки каждого TCP-соединения требуется «тройное рукопожатие»:
Только после этих трёх шагов соединение считается установленным.
На все эти шаги уходит время. Когда соединение нужно установить только один раз, время на лишние «рукопожатия» не тратится, а следовательно, увеличивается скорость.
Кроме того, в HTTP/2 отпадает необходимость в доменном шардинге.
Чтобы обойти ограничение на количество TCP-соединений в HTTP/1.1, разработчики выносили часть контента на поддомены. Данные с поддоменов загружались параллельно, и это помогало увеличить скорость.
Теперь это делать не нужно, так как разные данные передаются в одном соединении и никаких ограничений нет.
Чтобы сервер выполнил запрос наиболее точно, его заголовок должен содержать как можно больше уточняющих метаданных. А HTTP — это протокол без сохранения состояния. Это значит, что сервер не может хранить информацию из предыдущих запросов, и в результате клиенту приходится каждый раз посылать большое количество повторяющихся данных в заголовках.
Объём таких заголовков — около 500–800 байт служебных данных, а иногда и больше килобайта, если используются ещё файлы cookie.
Это делает всё сообщение в целом более объёмным. А чем больше размер данных, тем дольше они будут передаваться и тем больше будет задержка.
В HTTP/2 эту ситуацию исправило сжатие заголовков с помощью формата HPACK. Он кодирует и сжимает заголовки с помощью алгоритма Хаффмана. Вместе с этим клиент и сервер поддерживают общую, постоянно обновляемую таблицу заголовков. Это позволяет не передавать повторяющиеся заголовки, а восстанавливать их с помощью таблицы.
Данных передаётся меньше, а значит, запросы и ответы доходят быстрее.
Эта функция позволяет серверу передавать данные ещё до того, как клиент их запросил. Например, браузер загружает страницу и отправляет запрос на HTML. Но вместе с HTML для отрисовки страницы будут нужны ещё и CSS. Сервер не ждёт второго запроса на CSS и отправляет эти данные сразу вместе с запрошенными.
«Угаданные» сервером данные отправляются с помощью фрейма PUSH_PROMISE. Так клиент сможет понять, что это информация, которую он не запрашивал, и определить, нужна ли она ему. Если данные окажутся не нужны (например, потому что они уже есть в кеше), браузер может послать в ответ фрейм RST_STREAM (мы говорили о нём выше) и остановить передачу лишнего.
Это помогает избежать дублирования информации.
Таким образом, функция сокращает количество запросов к серверу, уменьшает нагрузку на него и ускоряет работу веб-приложений.
Данные в HTTP/2 по умолчанию передаются асинхронно, в произвольной последовательности. Однако эту последовательность можно задать. Вы можете определить, какие данные сервер должен отдавать в первую очередь, а какие можно отправить позже.
Протокол позволяет определить вес каждого потока — его значимость в плане приоритетности передачи. Вместе с этим HTTP/2 даёт возможность установить зависимость одного потока от другого.
Вес определяется в виде целого числа от 1 до 256. Чем больше число, тем более приоритетным будет поток.
Зависимость одного потока от другого указывается с помощью специального идентификатора, который отсылает к другому, «родительскому» потоку.
Например, если поток X зависит от потока Y, это значит, что Y — родительский поток, и он должен быть полностью обработан в первую очередь, а уже после него будет обрабатываться поток X.
Если потоки не зависят друг от друга, но имеют разный вес, на их обработку выделяется разное количество ресурсов пропорционально их весу.
Допустим, потоки X и Y не зависят друг от друга, но при этом X весит 10, а Y — 15. Давайте посчитаем, сколько процентов ресурсов будет выделено каждому:
Получается, на обработку потока X будет выделено 40% ресурсов, а на обработку Y — 60%.
Давайте рассмотрим, как это работает, на более развёрнутом примере.
Что означает эта схема:
Какие возможности даёт приоритизация:
С момента выхода HTTP/2 прошло уже много времени, и его успели много раз протестировать и сравнить с HTTP/1.1. Разные тесты показывают разные результаты, но большинство из них действительно подтверждают, что новая версия обходит предшественника в производительности.
Например, тест CCS-Tricks показал, что сайт с HTTP/2 загружается почти в 2 раза быстрее, чем ресурс с HTTP/1.1.
Для тестирования компания смоделировала реальный одностраничный сайт на WordPress. Для измерения скорости загрузки они использовали инструмент GTMetrix.
В результате с использованием HTTP/1.1 страница сайта загружалась 1,9 с.
А на HTTP/2 при тех же условиях время загрузки составило 1 с.
При этом, как видим, с использованием HTTP/2 уменьшилось количество запросов.
Испытания компании SolarWinds демонстрируют не столь впечатляющие результаты. Их тестирование показывает, что производительность HTTP/2 выше, чем у предшественника, всего на 13%.
Так же, как и в предыдущем исследовании, компания замеряла скорость сайта на WordPress. Для измерений они использовали Pingdom. Скорость проверялась 4 раза через каждые 30 минут. Из получившихся результатов они вывели средний показатель. И вот что получилось.
Сайт с HTTP/1.1 загружался 534 мс.
А тот же сайт на HTTP/2 загрузился за 464 мс.
Размер страницы; Среднее время загрузки
Так или иначе, HTTP/2 на данный момент является наиболее оптимизированной и быстрой версией основного протокола передачи данных в интернете.
CDN от EdgeЦентр поддерживает протокол HTTP/2. При этом наша сеть может доставлять контент по HTTP/2, даже если ваши серверы его не поддерживают.
Особенности EdgeЦентр CDN: