Новый протокол HTTP/3 близится к своей окончательной форме. Более ранние итерации уже были доступны в качестве экспериментальной функции, доступность и использование HTTP/3 растет. Так что же такое HTTP/3? Зачем он нужен так скоро после HTTP/2? Как его использовать? И особенно, как он улучшает веб-производительность? Давайте выясним.
Возможно, вы читали записи в блогах, слышали выступления на конференциях на эту тему и думаете, что знаете ответы. Вероятно, слышали что-то вроде: “HTTP/3 намного быстрее, чем HTTP/2 при потерях пакетов”, или “Соединения HTTP/3 имеют меньшую задержку и требуют меньше времени для их настройки”, и, вероятно, “HTTP/3 может отправлять больше ресурсов параллельно”.
В этих заявлениях и статьях обычно пропускаются важные технические детали, отсутствуют нюансы и, как правило, они верны лишь частично. Часто они создают впечатление, что HTTP/3 - это революция в производительности, в то время как на самом деле это более скромная (но все же полезная!) эволюция. Это вызывает опасения, потому что новый протокол, вероятно, не сможет оправдать эти высокие ожидания на практике. Боюсь, что это приведет к тому, что многие люди в конечном итоге разочаруются, а новички будут сбиты с толку нагромождением слепо распространяемой дезинформации.
Мы уже видели, как точно то же самое происходило с HTTP/2. Он был представлен как невероятная революция в производительности, с захватывающими новыми функциями, такими как сервер push, параллельные потоки и приоритизация. Мы смогли избавиться от упаквки всего в бандлы, снизить нагрузку на сервера и значительно упростить процесс загрузки страниц. Веб-сайты волшебным образом стали на 50% быстрее всего в один клик!
Теперь мы знаем, что сервер push на практике не работает, потоки и приоритизация часто плохо реализованы, следовательно, объединение ресурсов в бандлы и шардирование в некоторых ситуациях все еще являются хорошей практикой.
Аналогично, другие механизмы, настраивающие поведение протокола, например, предварительная загрузка ресурсов, часто не так просты, как кажется, и содержат ошибки, что затрудняет их правильное использование.
Исходя из этого важно предотвратить распространение такого рода дезинформации и нереалистичных ожиданий от HTTP/3.
В этой серии статей мы расскажем о новом протоколе, в частности о его производительности. Мы увидим, что, хотя в HTTP/3 действительно есть несколько новых многообещающих концепций, к сожалению, их влияние, вероятно, будет относительно ограниченным для большинства веб-страниц и пользователей (но потенциально критически важным для небольшого подмножества). HTTP/3 также довольно сложно настроить и использовать (правильно), поэтому будьте осторожны при настройке нового протокола.
Зачем нам HTTP/3?
Один из вопросов, с которым мы часто сталкиваемся, звучит так: “Зачем нам нужен HTTP/3 так скоро после HTTP/2, который был стандартизирован только в 2015 году?” Это действительно странно, пока вы не поймете, что на самом деле нам нужна была не новая версия HTTP, а скорее обновление базового протокола управления передачей (TCP).
TCP - это основной протокол, который предоставляет такие важные функции, как надежная и своевременная доставка данных при помощи других протоколов, такими как HTTP. Он позволяет множеству пользователей одновременно подключаться к сети Интернет и доставлять пакеты до адресата.
А вы знали?
При использовании HTTP вы на самом деле одновременно используете несколько протоколов. Каждый из протоколов в этом “стеке” имеет свои функции и обязанности (см. изображение ниже). Например, в то время как HTTP занимается URL-адресами и интерпретацией данных, Transport Layer Security (TLS) обеспечивает безопасность путем шифрования, а TCP - надежную передачу данных путем повторной передачи потерянных пакетов, в то время как Интернет-протокол (IP) направляет пакеты от одной конечной точки к другой через различные промежуточные устройства.
Это «наслоение» протоколов друг на друга делается для того, чтобы упростить повторное использование их функций. Протоколы более высокого уровня (например, HTTP) не должны заново реализовывать сложные функции (например, шифрование), потому что протоколы более низкого уровня (например, TLS) уже делают это за них. Другой пример: большинство приложений в Интернете используют протокол TCP для обеспечения полной передачи всех своих данных. По этой причине TCP является одним из наиболее широко используемых протоколов в Интернете.
TCP был краеугольным камнем Интернета на протяжении десятилетий, но в конце 2000-х начал показывать свой возраст. Предполагаемая замена, новый транспортный протокол под названием QUIC, достаточно отличается от TCP по нескольким ключевым параметрам, поэтому запуск HTTP/2 непосредственно поверх него будет затруднительным. Таким образом, HTTP/3 сам по себе является относительно небольшой модификацией HTTP/2, делающей его совместимым с новым протоколом QUIC, который включает в себя новые функции.
QUIC стал необходим, потому что TCP, существующий с первых дней Интернета, на самом деле не создавался с расчетом на максимальную эффективность. Во-первых, TCP требует «рукопожатия» для установки нового соединения. Это делается для того, чтобы убедиться в существовании как клиента, так и сервера, а также в том, что они готовы и способны обмениваться данными. Однако для этого также требуется полный переход по сети туда и обратно, прежде чем что-либо еще можно будет сделать с подключением. Если клиент и сервер географически удалены, то задержка времени приема-передачи данных (RTT - round-trip time) может составлять более 100 миллисекунд.
Во-вторых, TCP видит все передаваемые данные как один “файл” или поток байтов, даже если мы фактически используем его для передачи нескольких файлов одновременно (например, при загрузке веб-страницы, состоящей из множества ресурсов). На практике это означает, что если TCP-пакеты, содержащие данные из одного файла, будут потеряны, то все остальные файлы также будут задерживаться до тех пор, пока эти пакеты не будут отправлены вновь.
Это называется блокировкой в начале очереди (head-of-line (HoL) blocking). Хотя на практике эти недостатки вполне преодолимы (в противном случае мы бы не использовали TCP более 30 лет), они заметно влияют на протоколы более высокого уровня, такие как HTTP.
Со временем TCP продолжали развивать и обновлять , чтобы устранить некоторые из этих проблем и даже внедрить новые функции для повышения производительности. Например, TCP Fast Open сокращает время на рукопожатие, позволяя протоколам более высокого уровня отправлять данные с самого начала. А так же многопоточный (MultiPath) TCP. Здесь идея заключается в том, что ваш мобильный телефон, вероятно, имеет как Wi-Fi, так и сотовую связь (4G), так почему бы не использовать их одновременно для повышения пропускной способности и устойчивости к помехам?
Реализовать эти расширения TCP не так уж и сложно. Однако внедрить их использование в масштабах всего Интернета практически не реально. Поскольку TCP используется в каждом устройстве, которое умеет выходить в интернет, зачастую они имеют собственную встроенную реализацию протокола. Если она слишком древняя, не обновляется и/или содержит ошибки, то расширения не будут работать. Иными словами, все реализации должны знать о расширении, чтобы оно было полезным.
Это не было бы большой проблемой, если бы мы говорили только об устройствах конечного пользователя (таких как ваш компьютер, телефон или веб-сервер), поскольку их можно относительно легко обновить вручную. Однако между клиентом и сервером находится множество других устройств, которые также имеют свой собственный встроенный TCP-код (примеры включают брандмауэры (межсетевые защитные экраны), балансировщики нагрузки, маршрутизаторы, сервера кэширования, прокси-серверы и т.д.).
Эти промежуточные блоки сложнее обновлять, и они в целом более строги в отношении безопасности. Например, если устройство является брандмауэром, оно может блокировать весь трафик, содержащий неизвестные расширения. На практике оказывается, что огромное количество промежуточных элементов имеют определенное представление о TCP, в котором нет места для расширений.
Следовательно, могут потребоваться годы или даже десятилетия, прежде чем большиство из них обновится, чтобы использовать новые функции TCP в больших масштабах. Можно сказать, что развитие TCP стало практически невозможно.
Стало ясно, что для решения этих проблем нам потребуется протокол, который заменит TCP, а не его обновление. Однако из-за огромной сложности TCP и различия его реализации создание чего-то нового и лучшего с нуля стало колоссальной задачей. И в начале 2010-х годов было принято решение её отложить.
В конце концов, были проблемы не только с TCP, но и с HTTP/1.1. Разработчики решили разделить работу и сначала “исправить” HTTP /1.1, что привело к появлению HTTP/2.
Когда переход будет завершен, можно будет начать работу по замене TCP, который теперь называется QUIC. Первоначально предполагалось, что получится запускать HTTP/2 поверх QUIC, но на практике это сделало бы реализацию слишком громоздкой и неэффективной (в основном из-за дублирования функций).
Вместо этого HTTP/2 был скорректирован в нескольких ключевых местах, чтобы сделать его совместимым с QUIC. И новая версия в конечном итоге была названа HTTP/3 (вместо HTTP/2-over-QUIC), главным образом по маркетинговым соображениям и для ясности.
Таким образом, различия между HTTP/1.1 и HTTP/2 гораздо более существенны, чем различия между HTTP/2 и HTTP/3.
Вывод
Ключевым выводом здесь является то, что на самом деле нам нужен был не HTTP/3, а скорее “TCP/2”, а HTTP/3 мы получили “бесплатно”. Основные функции, которые мы ждем в HTTP/3 (ускоренная настройка соединения, меньше блокировок, миграция соединений и т. д.), на самом деле реализованы в QUIC.