HTTP/2

В прошлом году в мире сетевых технологий произошло очень важное событие: была утверждена и стандартизирована новая версия протокола HTTP — HTTP/2. HTTP/2 уже поддерживается в популярных веб-серверах: Apache и Nginx. Идёт работа по внедрению HTTP/2 в IIS. Реализована поддержка и в большинстве современных браузеров.

Использование HTTP/2 за последнее время существенно расширилось.

По данным на середину 2015 года, процент сайтов и веб-сервисов, перешедших на HTTP/2, был невелик ― всего 0,4%. Совсем свежая статистика (январь 2016) свидетельствует о значительном росте: с 0,4 до 6,5%. Есть все основания полагать, что в ближайшее время темпы роста будут увеличиваться.

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

От HTTP к HTTP/2


Немного истории


Первое описание протокола HTTP (HyperText Transfer Protocol) было опубликовано в 1991 году. В 1999 году была разработана и описана версия HTTP 1.1, используемая и по сей день. В то далёкое время (почти 20 лет назад) веб-сайты были совсем не такими, как сейчас. За относительно небольшой период времени сайты стали «весить» гораздо больше. Домашняя страница среднестатического современного сайта содержит примерно 1,9 МБ данных: изображения, JS, CSS и многое другое.

Из-за ограничения на количество одновременных подключений в HTTP/1.1 загрузка страниц, содержащих большое количество «тяжёлого» контента, осуществляется медленно. Можно выделить два пути решения этой проблемы. Первый заключается в использовании различных техник оптимизации производительности (о некоторых из них мы уже писали), а второй — в попытке модификации самого протокола HTTP с целью устранения возможных узких мест. Рассмотрим такие попытки более подробно.

Первый масштабный проект реформирования HTTP был представлен в 2009 году инженерами Google. Это протокол SPDY, целью которого в первую очередь было ускорение работы веб-сайтов и приложений путём модификации традиционных способов приёма и отправки запросов.

SPDY требует поддержки как на стороне сервера, так и на стороне клиента. Разработчики Google создали специализированные модули для Apache (mod_spdy) и для Nginx (ngx_http_spdy_module). Поддерживается он и практически во всех популярных браузерах.

HTTP/2, представленный шестью годами позже, во многом основывается на SPDY. Новая версия HTTP была создана рабочей группой Hypertext Transfer Protocol working group. В мае 2015 года спецификация HTTP/2 была опубликована как RFC 7540.

Протокол HTTP/2 обратно совместим с HTTP/1.1. Изменения, направленные на устранение узких мест и повышения производительности, во многом продолжают линию SPDY. Рассмотрим вкратце наиболее важные из них.

HTTP/2: основные нововведения


Мультиплексирование


Возможно, это самое главное преимущество HTTP/2. В HTTP/1.1 для каждого запроса требуется устанавливать отдельное TCP-соединение. Мультиплексирование же позволяет браузеру выполнять множество запросов в рамках одного TCP-соединения:

HTTP/2

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

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

Приоритеты


Ещё одно нововведение HTTP/2 — это приоритизация. Каждому запросу можно назначить приоритет.
Существует два подхода к назначению приоритетов: на основе веса и на основе зависимостей.

В первом подходе каждый поток получает определённый вес. Потом на основе веса сервер распределяет нагрузку между потоками. Такой подход уже использовался в протоколе SPDY.

Второй метод, являющийся основным в HTTP/2, заключается в следующем: браузер просит сервер загружать определённые элементы контента в первую очередь. Например, браузер может попросить сервер сначала загрузить CSS-файлы или JavaScript, а уже потом — HTML или изображения.

В HTTP/2 приоритизация является не обязательным, а желательным методом. Однако мультиплексирование без неё работать должным образом не будет. Скорость загрузки может быть даже ниже, чем HTTP/1.1. Ресурсы с более низким приоритетом будут занимать полосу, что приведёт снижению производительности.

Сжатие HTTP-заголовков


Современная веб-страница состоит из множества элементов: изображения, JS, CSS и другие. В запросе на загрузку каждого из этих элементов браузер передаёт HTTP-заголовок. Отправляя запрошенные элементы, сервер также добавляет к ним заголовок. Всё это сопряжено с излишним расходованием ресурсов.

В HTTP/2 заголовки передаются в сжатом виде. Благодаря этому уменьшается количество информации, которой обмениваются между собой сервер и браузер. Вместо алгоритмов gzip/deflate используется HPACK. Это снижает уязвимость к атакам типа BREACH.

HTTP/2 и безопасность


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

Это нужно не только для HTTP/2. В поиске Google использование безопасного соединения является одним из критериев ранжирования. Браузеры (см. здесь и здесь) скоро будут помечать сайты, не поддерживающие https, как «небезопасные». Добавим также, что многие возможности HTML5 ― например, геолокация ― без безопасного соединения будут недоступны.

Базовая настройка HTTP/2 в Nginx и Apache


Приведём краткие инструкции по включению и базовой настройке HTTP/2 в Nginx и Apache. Как уже было сказано выше, большинство современных браузеров работают с HTTP/2 только через TLS, поэтому в конфигурации вашего веб-сервера должны быть прописаны соответствующие настройки.

Nginx


Поддержка HTTP/2 реализована только в новейших версиях Nginx (1.9.5 и выше). Если у вас установлена другая версия, вам потребуется обновить её.

После этого откройте конфигурационный файл /etc/nginx/nginx.conf и найдите в секции server следующую строку:

listen 443 ssl;


и замените её на:

listen 443 ssl http2;


Сохраните внесённые изменения и перезагрузите Nginx:

$ sudo service nginx reload


Apache


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

# for a https server
Protocols h2 http/1.1

# for a http server
Protocols h2c http/1.1


После этого перезапустите Apache. Вот и всё — для базовой настройки этого вполне достаточно.

HTTP/2 и оптимизация сайтов


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

Многие способы оптимизации, успешно используемые в HTTP/1.1, в HTTP/2 работать не будут. Некоторые из них потребуется модифицировать, а от некоторых ― отказаться вообще. Рассмотрим этот вопрос более подробно.

Объединение изображений в спрайты


В HTTP/1.1 было удобнее загрузить одно большое изображение, чем делать множество запросов и загружать много маленьких. Это обусловлено тем, что запросы ставятся в очередь друг за другом. Самый распространённый способ увеличения скорости загрузки заключался в объединении множественных небольших изображений в спрайт-файл.

Спрайт возвращался в ответ на единственный запрос. Даже если пользователь заходил на страницу, на которой находится всего одно небольшое изображение, нужно было загрузить весь спрайт.

В HTTP/2 c его мультиплексированием таких проблем нет, однако использование спрайтов в определённых ситуациях может оказаться полезным. Объединение нескольких изображений в спрайт (особенно если все эти изображения находятся на одной странице) помогает улучшить сжатие и таким образом снизить общий объём загружаемых данных.

Встраивание изображений с помощью DataURI


Ещё один популярный способ решения проблемы множественных HTTP-запросов в HTTP/1.1 ― встраивание изображений с использованием Data URI. Это существенно увеличивает в размере таблицу стилей.

Если одновременно со встраиванием изображений для оптимизации используется ещё и конкатенация JS и CSS, пользователю скорее всего придётся загрузить весь соответствующий код, даже если он не будет посещать страницу с этими изображениями.
В HTTP/2 такая практика скорее ухудшит, а не улучшит производительность.

Конкатенация JS и CSS


Для оптимизации работы сайтов часто используется конкатенация небольших CSS- и JS-файлов. Много маленьких файлов объединяются в один большой. Таким образом удаётся обойти лимит на количество HTTP-запросов.

Однако при использовании конкатенации может возникнуть та же проблема, что и со спрайтами: зайдя на какую-то одну страницу сайта, пользователь загрузит все используемые на нём СSS- и JS-файлы (при этом очень вероятно, что большинство и�� этих файлов ему никогда не понадобятся). Конечно, можно тщательно отбирать файлы для каждой страницы сайта, но это будет занимать слишком много времени.

Ещё одна сложность заключается в том, что все элементы конкатенированного файла нужно вычищать из кэша одновременно. Невозможно сделать так, чтобы для одних элементов была выставлена одна дата истечения срока действия, а для других (которые к тому же и используются гораздо чаще) — другая. Если изменить хотя бы одну строку в CSS — срок действия истечёт сразу у всех элементов.

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

Доменное шардирование


В HTTP/1.1 имеется ограничение на количество открытых соединений. Чтобы обойти это ограничение, приходится загружать статические ресурсы с нескольких поддоменов одного домена. Такой приём называется доменным шардированием; он часто используется, например, для страниц с большим количеством изображений. Это помогает увеличить скорость загрузки, но вместе с тем и создаёт дополнительные проблемы.

С переходом HTTP/2 необходимость в доменном шардировании отпадает. Вы можете запросить столько ресурсов, сколько вам требуется. Более того, в случае с HTTP/2 шардирование не улучшит производительность, а приведёт скорее к противоположному эффекту, так как создаст дополнительные TCP-соединения и будет мешать приоритизации.

Когда переходить?


Когда планировать переход на HTTP/2? Однозначного ответа на этот вопрос нет и быть не может. Дадим, однако, одну подсказку: регулярно просматривайте логи посещаемости вашего сервиса. Когда вы увидите, что большая часть посетителей используют поддерживающие HTTP/2 браузеры — можно переходить. На текущий момент поддержка HTTP/2 реализована в Chrome (в том числе и в мобильной версии для Android), Firefox, Opera, Edge, Safari.

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

Если вы планируете запускать новый веб-сервис — задумайтесь о перспективе перехода на HTTP/2. Конечно, вам ещё придётся использовать HTTP/1.1 в течение какого-то времени, но уже сейчас вы можете принять меры по оптимизации, которые облегчат вам жизнь в будущем.

Полезные ссылки


В заключение приведём для заинтересованных читателей несколько полезных ссылок по теме:



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