Ответ
HTTP/2 — это вторая основная версия протокола HTTP, пришедшая на смену HTTP/1.1. Его главной целью было повышение производительности за счет решения ключевых проблем предшественника.
В отличие от текстового HTTP/1.1, HTTP/2 является бинарным протоколом. Это упрощает парсинг и делает его менее подверженным ошибкам.
Ключевые нововведения:
- Мультиплексирование (Multiplexing): Позволяет одновременно отправлять несколько запросов и получать несколько ответов в рамках одного TCP-соединения. Это решает проблему "Head-of-line blocking" на уровне HTTP, когда медленный ответ блокировал все последующие.
- Приоритизация потоков (Stream Prioritization): Клиент может указать браузеру, какие ресурсы важнее (например, сначала загрузить CSS, а потом изображения), что позволяет оптимизировать отрисовку страницы.
- Сжатие заголовков (Header Compression, HPACK): Заголовки в HTTP/1.1 часто дублируются и передаются в текстовом виде. HPACK сжимает их, значительно уменьшая объем передаваемых метаданных.
- Server Push: Сервер может отправлять ресурсы клиенту до того, как он их запросит. Например, вместе с
index.html
сервер может сразу отправитьstyle.css
иscript.js
, так как он предполагает, что они понадобятся клиенту.
Пример Server Push в Go:
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// Проверяем, поддерживает ли клиент Server Push
if pusher, ok := w.(http.Pusher); ok {
// Отправляем CSS заранее, не дожидаясь запроса от клиента
if err := pusher.Push("/static/style.css", nil); err != nil {
log.Printf("Failed to push: %v", err)
}
}
// Отдаем основную страницу
fmt.Fprintln(w, "<html>...</html>")
})
Важное ограничение:
- HTTP/2 не решает проблему Head-of-Line blocking на уровне TCP. Если один TCP-пакет теряется, все потоки внутри соединения ждут его переотправки. Эту проблему решает уже следующий протокол — HTTP/3, работающий поверх QUIC (UDP).