от корней до кончиков / Habr
Протокол прикладного уровня HTTP лежит в основе интернета. Он начал свою жизнь в 1991 году как HTTP/0.9, а к 1999 году превратился в HTTP/1.1, который был стандартизирован Инженерным советом Интернета (IETF).HTTP/1.1 долго всех удовлетворял, но растущие потребности Сети потребовали апгрейда — и в 2015 году приняли HTTP/2. На этом история не закончилась: совсем недавно IETF анонсировал новую версию HTTP/3. Для некоторых это стало неожиданностью и вызвало некоторое замешательство. Если вы не отслеживаете работу IETF, может показаться, что HTTP/3 появился из ниоткуда. Тем не менее, мы можем отследить его происхождение по истории экспериментов и эволюции веб-протоколов, в частности, транспортного протокола QUIC.
Если вы не знакомы с QUIC, мои коллеги по Cloudflare довольно подробно осветили разные аспекты: например, см. статьи о реальных недостатках современного HTTP и подробности о протоколе транспортного уровня. Мы собрали эти и другие материалы на сайте cloudflare-quic.com. А если интересно, обязательно ознакомьтесь с quiche: это наша собственная реализация QUIC, написанная на Rust с открытым исходным кодом.
HTTP/3 — трансляция транспортного протокола QUIC для прикладного уровня. Название HTTP/3 официально утвердили лишь недавно, в 17-й версии черновика (draft-ietf-quic-http-17). Его предложили в конце октября 2018 года, а консенсус был достигнут на встрече IETF 103 в Бангкоке в ноябре.
Раньше НТТР/3 был известен как HTTP по QUIC, а до этого — как HTTP/2 по gQUIC, а ещё раньше — SPDY по gQUIC. Но суть в том, что HTTP/3 — просто новый синтаксис HTTP, который работает на протоколе IETF QUIC, мультиплексированном и безопасном транспорте на основе UDP.
В этой статье рассмотрим историю некоторых из предыдущих названий HTTP/3 и представим мотивацию последнего изменения имени. Вернёмся к первым дням HTTP и всему, что произошло за это время. Если хотите получить полную картину, можете сразу перейти к концу статьи или открыть эту очень подробную версию SVG.
Слоёный пирог HTTP/3
Непосредственно перед тем, как сосредоточиться на HTTP, стоит напомнить, что существует два протокола с названием QUIC. Как мы уже объясняли, gQUIC обычно используется как сокращение от Google QUIC (исходный протокол), и QUIC — как версия IETF, которая отличается от gQUIC.
С начала 90-х потребности интернета изменились. У нас появились новые версии HTTP и новый уровень безопасности в виде протокола TLS (Transport Layer Security). В этой статье затронем только TLS, а в других статьях нашего блога можно более подробно изучить тему.
Историю HTTP и TLS невозможно выразить простым списком дат, поскольку некоторые ветви развивались параллельно и перекрывались во времени. Когда вы пытаетесь соединить все точки за почти 30 лет истории интернета, не обойтись без визуализации. Поэтому я сделал такой график: Cloudflare Secure Web Timeline. (примечание: технически это кладограмма, хотя людям более привычно слово «график»).
Ради красоты я отбросил часть информации, сосредоточившись только на успешных ветвях в пространстве IETF. Например, здесь не показаны усилия рабочей группы HTTP-NG консорциума W3, а также некоторые экзотические технологии, произношение которых до сих пор пытаютс объяснить авторы: HMURR (произносится «hummer») и WAKA (произносится «wah-kah»).
В следующих разделах пройдёмся по этой кладограмме и рассмотрим некоторые переломные моменты в истории HTTP. Надеюсь, это поможет понять, почему стандартизация выгодна всем, и как к этому вопросу подходит IETF. Поэтому начнём с очень краткого обзора темы, прежде чем вернуться к самому графику. Смело пропустите следующий раздел, если вы уже знакомы с IETF.
Обычно стандарты определяют общую компетенцию, сферу применения, ограничения, применимость и другие соображения. Стандарты существуют разных форм и размеров. Они могут быть неформальными (стандарт де-факто) или формальными (согласованными/опубликованными организацией, определяющей стандарты, такой как IETF, ISO или MPEG). Стандарты используются во многих областях, существует даже формальный британский стандарт приготовления чая — BS 6008. Первые определения протоколов HTTP и SSL были опубликованы за пределами IETF: на графике они отмечены красными линиями. Но повсеместное использование сделало их стандартами де-факто.
В какой-то момент приняли решение формализовать эти протоколы (некоторые причины описаны ниже). Стандарты интернета обычно определяются в IETF, который руководствуется неофициальным принципом «примерного консенсуса и действующего кодекса» на основе реальных приложений в интернете. Это отличается от подхода «чистой комнаты», когда некто пытается разработать идеальные протоколы в вакууме.
Стандарты IETF широко известны как RFC. Это сложно объяснить вкратце, поэтому рекомендую статью «Как читать RFC» от сопредседателя рабочей группы QUIC Марка Ноттингема. Рабочая группа или WG — это, по сути, просто список рассылки.
Каждый год проходит три собрания для личных встреч членов всех рабочих групп, если они того пожелают. Повестка дня на эти недели может быть очень насыщенной, времени не хватает для углубленного обсуждения технических вопросов. Поэтому некоторые предпочитают устраивать ещё промежуточные совещания между общими совещаниями IETF. Рабочая группа по QUIC с 2017 года провела несколько промежуточных заседаний, полный список доступен на странице встреч.
На этих совещаниях есть возможность встретиться со специалистами из других организаций, таких как Совет по архитектуре интернета (IAB) или Исследовательская группа Интернет-технологий (IRTF). В последние годы в выходные перед заседанием IETF традиционно проводится хакатон IETF. Здесь разрабатывается реальный код и, что важно, проходят тесты совместимости. Это помогает найти проблемы в спецификациях, которые можно обсудить непосредственно на встрече.
Важно понимать, что RFC не возникают из ниоткуда. Они проходят целый процесс. Обычно он начинается с черновика IETF Internet Draft (I-D), который представляют на рассмотрение. В случае, когда уже опубликована спецификация, подготовка I-D станет простым переформатированием. Срок службы I-D составляет 6 месяцев с даты публикации. Чтобы он оставался активным, необходимо публиковать новые версии. На практике нет ничего страшного в том, что срок I-D истекает. Такое происходит довольно часто. Документы по-прежнему хранятся на веб-сайте IETF и открыты для всех.
На кладограмме черновики представлены фиолетовым цветом. У каждого своё название в формате draft-{автор}-{рабочая группа}-{тема}-{версия}. Поле WG необязательно, оно может указывать на будущую рабочую группу IETF и иногда меняется. Если I-D утверждён IETF или инициирован непосредственно внутри IETF, то черновик называется draft-ietf-{рабочая группа}-{тема}-{версия}. I-D могут разветвляться, сливаться или затухать. Версия начинается с 00 и с каждым новым проектом увеличивается на единицу. Например, четвёртый черновик получит номер версии 03. Каждый раз при изменении названия I-D его версия сбрасывается до 00.
Важно отметить, что любой желающий может представить в IETF свой черновик: их нельзя рассматривать в качестве стандартов. Но если процесс стандартизации достигнет консенсуса и итоговый документ пройдёт проверку, мы получим RFC. На этом этапе имя снова изменяется. Каждый RFC получает уникальный номер, например, RFC 7230. Документы с таким статусом представлены в виде синих линий.
RFC запрещено изменять. То есть изменения в RFC требуют принятия документа с новым номером. Изменения разрешены только для исправления редакционных или технических ошибок или для простой оптимизации вёрстки. Новые RFC могут полностью заменить старые или дополнить их.
Все документы IETF находятся в открытом доступе на сайте http://tools.ietf.org. Лично мне кажется немного удобнее IETF Datatracker, потому что там визуально отображается путь документа от I-D до RFC.
Ниже пример, который показывает развитие стандарта RFC 1945, то есть HTTP/1.0.
История RFC 1945 в интерфейсе IETF Datatracker
Интересно, что в ходе работы я обнаружил, что вышеприведенная визуализация неверна. По какой-то причине отсутствует draft-ietf-http-v10-spec-05. Поскольку срок жизни I-D составляет 6 месяцев, вероятно, он истёк до принятия RFC, хотя в реальности черновик был активен до августа 1996 года.
После небольшого теоретического вступления можем приступить к изучению кладограммы. В этом разделе представлены некоторые выдержки с наиболее важными частями. Каждая точка обозначает дату предоставления документа или функции. Для ясности у документов IETF опущены номера проектов, но все они есть в полной версии.
HTTP появился в 1991 году как протокол HTTP/0.9, а в 1994 году был опубликован черновик draft-fielding-http-spec-00. Вскоре его принял IETF, в результате чего название изменилось на draft-ietf-http-v10-spec-00. После шести редакций черновика в 1996 году был принят стандарт RFC 1945 — HTTP/1.0.
Однако ещё до завершения работы над HTTP/1.0 был запущен отдельный проект HTTP/1.1. Версию черновика draft-ietf-http-v11-spec-00 опубликовали в ноябре 1995-го, а официально приняли как RFC 2068 в 1997 году. Острый глаз заметит, что кладограмма не совсем отражает эту последовательность событий — неудачный глюк инструмента визуализации. Я старался по возможности минимизировать такие проблемы.
В середине 1997 года начался пересмотр HTTP/1.1 как draft-ietf-http-v11-spec-rev-00. Он завершился в 1999 году с публикацией RFC 2616. До 2007 года в мире IETF HTTP всё было тихо. Вернёмся к этому чуть позже.
Переключим внимание на траекторию SSL. Мы видим, что спецификация SSL 2.0 вышла примерно в 1995 году, а SSL 3.0 — в ноябре 1996 года. Интересно, что SSL 3.0 утверждён в стандарте RFC 6101, который появился только в августе 2011 года. Он находится в исторической секции. Согласно IETF, она создана «для документирования идей, которые рассмотрены и отброшены, или протоколов, которые уже существовали к тому времени, когда принято решение их задокументировать». В данном случае был нужен документ IETF с описанием SSL 3.0, чтобы повсеместно использовать его в качестве канонической ссылки.
Нас больше интересует, как SSL вдохновил инженеров на разработку TLS, которая началась с черновика draft-ietf-tls-protocol-00 в ноябре 1996 года. Он прошёл через 6 черновых версий и был опубликован как RFC 2246 — TLS 1.0 в начале 1999 года.
В 1995-1999 годах протоколы SSL и TLS использовались для защиты HTTP-соединений в интернете. Это прекрасно работало как стандарт де-факто. Только в январе 1998 года с публикации черновика draft-ietf-tls-https-00 начался процесс официальной стандартизации HTTPS. Работа завершилась в мае 2000 года публикацией RFC 2616 — HTTP по TLS.
TLS продолжал развиваться с 2000 по 2007 год, с принятием стандартов TLS 1.1 и 1.2. Потом случилась семилетняя пауза, прежде чем начались работы над следующей версией протокола TLS, которую опубликуют в виде draft-ietf-tls-tls13-00 в апреле 2014 года, а после 28 черновиков утвердят как RFC 8446 — TLS 1.3 в августе 2018 года.
После небольшого знакомства с кладограммой, надеюсь, стало лучше понятно, как работает IETF. При создании стандартов исследователи или инженеры разрабатывают экспериментальные протоколы для конкретных случаев использования. На различных уровнях они экспериментируют с публичными или частными протоколами. Полученная информация позволяет выявить проблемы или улучшить протокол. Публикация работы помогает объяснить эксперимент, собрание мнение более широкого круга специалистов или найти помощь лице других исполнителей. Если другие участники примут эту работу на ранней стадии, то она станет стандартом де-факто, а в конечном счёте возникнет достаточный импульс для официальной стандартизации.
Официальный статус протокола — важный фактор для организаций, которые думают о его использовании. Формальный процесс стандартизации повышает привлекательность стандарта де-факто, поскольку обычно обеспечивает стабильность. Управление и руководство берёт на себя авторитетная организация, такая как IETF, которая отражает интересы и опыт многих участников. Но следует отметить, что не все формальные стандарты становятся успешными.
Процесс создания стандарта почти так же важен, как и сам стандарт. Обработка первоначальной идеи, приглашение к обсуждению людей с более широкими знаниями, опытом и вариантами использования — всё это помогает создать что-то более полезное для широкой аудитории. Однако процесс стандартизации не всегда лёгок. Есть подводные камни и препятствия. Иногда процесс занимает так много времени, что результат уже не актуален.
В каждой организации, определяющей стандарты, обычно есть собственный процесс, ориентированный на её сферу деятельности и участников. Объяснение всех подробностей, как работает IETF, выходит далеко за рамки этой статьи. Если вам это интересно, отличной отправной точкой станет страница «Как мы работаем» на сайте IETF. Как обычно, лучший способ во всём разобраться — принять участие самому. Достаточно присоединиться к списку рассылки или к обсуждению в соответствующем репозитории GitHub.
Cloudflare гордится тем, что одной из первых внедряет новые протоколы, как было с HTTP/2 и другими технологиями. Мы также тестируем экспериментальные и ещё не утверждённые функции, такие как TLS 1.3 и SPDY.
Запуск реального кода помогает понять, насколько хорошо протокол будет работать на практике. Мы объединяем экспертные знания с экспериментальной информацией, чтобы помочь улучшить код и, где это имеет смысл, сообщаем о проблемах или улучшениях в рабочую группу, которая стандартизирует протокол.
Тестирование новшеств — не единственный приоритет. Настоящий инноватор всегда знает, когда следует отложить инновацию до лучших времён. Иногда это относится к протоколам, ориентированным на безопасность: например, Cloudflare отключил SSLv3 по умолчанию из-за уязвимости POODLE. В других случаях протоколы заменяются более технологически продвинутыми: например, мы заменили SPDY на HTTP/2.
Введение и отключение протоколов на Cloudflare представлено оранжевыми линиями. Вертикальные ориентиры помогают соотносить события Cloudflare с соответствующими документами IETF. Например, Cloudflare представила поддержку TLS 1.3 в сентябре 2016 года, а окончательный документ RFC 8446 был опубликован почти два года спустя, в августе 2018 года.
HTTP/1.1 — очень успешный протокол. График не показывает особой активности IETF после 1999 года. Но в реальности годы активного использования протокола дали опыт и проявили скрытые проблемы RFC 2616, в том числе некоторые проблемы совместимости. Кроме того, протокол расширился другими RFC, такими как 2817 и 2818. В итоге, в 2007 году было принято решение начать деятельность по улучшению спецификации HTTP. Она получила название HTTPbis (где «bis» происходит от латинского слова «два», «дважды» или «повтор»). Первоначальный устав новой рабочей группы хорошо описывает проблемы, которые она пыталась решить.
В общем, в HTTPbis начался рефакторинг RFC 2616. Он включает в себя исправления ошибок и внедрение некоторых аспектов из других спецификаций, которые опубликованы в то же время. Было принято решение разделить документ на части. В результате, в декабре 2007 года было опубликовано шесть черновиков:
- draft-ietf-httpbis-p1-messaging
- draft-ietf-httpbis-p2-semantics
- draft-ietf-httpbis-p4-conditional
- draft-ietf-httpbis-p5-range
- draft-ietf-httpbis-p6-cache
- draft-ietf-httpbis-p7-auth
На диаграмме показано, как продвигалась работа в течение длительного семилетнего процесса разработки. До окончательной стандартизации было принято 27 черновиков. В июне 2014 года вышла так называемая серия RFC 723x (где x колеблется от 0 до 5). Председатель рабочей группы по HTTPbis отметил это достижение фразой «RFC2616 мёртв». Если кто не понял, новые документы отправили в архив старый RFC 2616.
Пока IETF занимался доработкой RFC 723x, мир не стоял на месте. Люди продолжали расширять и дополнять HTTP. Среди них и инженеры Google, которые стали экспериментировать с собственным протоколом под названием SPDY (произносится “speedy”). Они заявили, что этот протокол ускоряет загрузку веб-страниц, что является важнейшей функцией HTTP. В конце 2009 года анонсировали первую версию, а в 2010 году быстро появился SPDY v2.
Не хочу вдаваться в технические подробности SPDY, но важно понимать, что SPDY взял основные парадигмы HTTP и немного изменил формат обмена для оптимизации. Оглядываясь назад, мы видим, что у HTTP чётко разграничены семантика и синтаксис. Семантика описывает концепцию обмена запросами и ответами, в том числе методы, коды состояния, поля заголовка (метаданные) и тела (полезные данные). Синтаксис описывает, как сопоставить семантику с байтами в сети.
У HTTP/0.9, 1.0 и 1.1 много общей семантики. Они также используют общий синтаксис в виде символьных строк, отправляемых через TCP-подключения. SPDY взял семантику HTTP/1.1 и изменил синтаксис на двоичный. Это действительно интересная тема, но сегодня мы не будем углубляться в эту кроличью нору.
Эксперименты со SPDY показали, что изменение синтаксиса HTTP действительно приносит эффект. В то же время важно сохранить существующую семантику. Например, сохранение формата URL для использования https://
позволило избежать многих проблем, которые могли повлиять на внедрение HTTPS.
Увидев некоторые положительные результаты, IETF решил, что пришло время рассмотреть варианты для HTTP/2.0. На слайдах с сессии HTTPbis, состоявшейся во время заседания IETF 83 в марте 2012 года, обозначены требования и цели, которые поставили перед собой разработчики. Там же чётко заявлено: «HTTP/2.0 только означает, что транспортный протокол (wire format) не совместим с HTTP/1.x»
В ходе этой встречи сообществу предложили высказать свои идеи. Среди поданных на рассмотрение черновиков были draft-mbelshe-httpbis-spdy-00, draft-montenegro-httpbis-speed-mobility-00 и draft-tarreau-httpbis-network-friendly-00. В конечном итоге черновик SPDY приняли, а в ноябре 2012 года началась работа над draft-ietf-httpbis-http2-00. После 18 черновиков в течение чуть более двух лет появился RFC 7540 — HTTP/2. К 2015 году синтаксис HTTP/2 ушёл ровно настолько, чтобы сделать HTTP/2 и SPDY несовместимыми.
Эти годы стали очень напряжённым периодом для рабочих групп, которые параллельно проводили рефакторинг HTTP/1.1 и принимали HTTP/2. Это резко контрастирует с многолетним спокойствием в начале 2000-х годов. Обязательно ознакомьтесь с полной кладограммой, чтобы по-настоящему оценить объём проделанной работы.
Несмотря на стандартизацию HTTP/2, эксперименты с SPDY приносят пользу до сих пор. Cloudflare представила поддержку SPDY в августе 2012 года и убрала только в феврале 2018 года, когда наша статистика показала, что её запрашивает менее 4% веб-клиентов. Между тем, вскоре после публикации RFC в декабре 2015 года мы ввели поддержку HTTP/2, когда анализ показал заметную поддержку веб-клиентов.
Протоколы SPDY и HTTP/2 по умолчанию используют TLS. Внедрение универсального SSL в сентябре 2014 года позволило гарантировать, что все пользователи Cloudflare воспользуются новыми протоколами по мере их внедрения.
Google продолжал экспериментировать и до 2015 года выпустил ещё версии SPDY v3 и v3.1. Они также начали работать над протоколом gQUIC, первый черновик которого опубликовали в начале 2012 года.
В ранних версиях gQUIC использовался синтаксис HTTP SPDY v3. Такой выбор имел смысл, потому что HTTP/2 ещё не утвердили. Бинарный синтаксис SPDY упакован в пакеты QUIC, которые отправляются в датаграммах UDP. Это отход от транспорта TCP, на который традиционно полагался HTTP. Вся система в сборе выглядела так:
Слоёный пирог SPDY по gQUIC
Для повышения производительности gQUIC применили хитрые трюки. Один из них — размыть чёткую границу между приложением и транспортом. На практике это означало, что gQUIC поддерживает только HTTP. Эта связь была настолько прочной, что gQUIC, который в то время называли QUIC, стал рассматриваться как кандидат на следующую версию HTTP. Хотя в дальнейшем в QUIC внесли много изменений, по сей день многие считают, что он поддерживает только HTTP. К сожалению, это приводит к постоянной путанице при обсуждении протокола.
gQUIC продолжал развиваться и в конце концов переключился на синтаксис, гораздо более близкий к HTTP/2. Настолько близкий, что большинство людей стали называть его «HTTP/2 по QUIC». Но из-за технических ограничений проявились некоторые очень тонкие различия. Один из примеров связан с сериализацией и обменом заголовками HTTP. Это незначительное различие, но на практике оно означает, что HTTP/2 по gQUIC несовместим с HTTP/2 от IETF.
Последнее, но не менее важное: всегда следует учитывать аспекты безопасности интернет-протоколов. А разработчики gQUIC решили отказаться от TLS в пользу другого подхода под названием QUIC Crypto. Одно из интересных нововведений там — новый метод ускорения рукопожатий. После установки безопасного сеанса с сервером клиент может повторно использовать информацию и зафиксировать «нулевое» время рукопожатия, то есть 0-RTT. Эту хитрость позже включили в протокол TLS 1.3.
Почти.
Теперь мы поняли, как работает стандартизация. Так вот, рассмотрение gQUIC шло по тому же сценарию. В июне 2015 года был представлен первый черновик draft-tsvwg-quic-protocol-00, озаглавленный «QUIC: безопасный и надёжный транспорт на основе UDP для HTTP/2». Но не забывайте, что в конце концов синтаксис протокола почти довели до совместимости с HTTP/2.
Компания Google объявила, что «BoF пройдёт на встрече IETF 93 в Праге». Если вам интересно, что такое BoF, пожалуйста, обратитесь к RFC 6771. Если вкратце, то BoF (Birds of a Feather) — это неформальная встреча на конференции.
По итогу обсуждения с IETF было решено, что у QUIC много преимуществ на транспортном уровне, следует отделить этот протокол от HTTP и вновь ввести чёткое разделение между слоями. Кроме того, для этого протокола решили вернуть рукопожатие на основе TLS (что не так уж плохо, ведь к этому моменту уже разработали TLS 1.3 со схемой 0-RTT).
Примерно через год, в 2016 году, вышел новый набор черновиков:
Вот где снова возникла путаница: draft-shade-quic-http2-mapping-00 называется «Семантика HTTP/2 с использованием транспортного протокола QUIC» и описывает «отображение семантики HTTP/2 по QUIC». Однако это неправильное название. Суть HTTP/2 в изменении синтаксиса при сохранении семантики. Кроме того, «HTTP/2 по gQUIC» никогда не был точным описанием синтаксиса, по причинам, которые я изложил ранее. Имейте это в виду при знакомстве с дальнейшими событиями.
Данная версия QUIC от IETF должна стать совершенно новым транспортным протоколом. Это серьёзное предприятие, поэтому IETF постаралась оценить интерес к проекту со стороны своих членов. Для этого на встрече IETF 96 в Берлине в 2016 году состоялась сессия BoF (слайды). Мне посчастливилось лично присутствовать на том собрании, которое привлекло сотни участников, о чём свидетельствует фотография Адама Роуча. В итоге был достигнут консенсус: QUIC будет принят и стандартизирован в IETF.
Первый черновик IETF QUIC draft-ietf-quic-http-00 для трансляции HTTP на транспорт QUIC логично упростил название протокола до «HTTP по QUIC» (HTTP over QUIC). К сожалению, работу не довели до конца, поэтому по всей организации использовались разные термины HTTP/2. Новый редактор хранилища черновиков стандартов Майк Бишоп увидел проблему и начал исправлять неправильные упоминания HTTP/2. В следующей версии протокола описание изменилось на «сопоставление семантики HTTP на QUIC» (mapping of HTTP semantics over QUIC).
Постепенно, с течением времени и новыми версиями, термин «HTTP/2» стали использовать реже, при необходимости просто указывая ссылки на RFC 7540. Спустя два года в октябре 2018 года вышла семнадцатая по счёту версия черновика (номер 16). Хотя у протокола HTTP over QUIC есть сходство с HTTP/2, по сути это независимый и не совместимый синтаксис HTTP. Тем не менее, для людей, которые не слишком пристально следят за работой IETF (а это очень большой процент населения Земли), название документа не отражает эту разницу. Одна из главных задач стандартизации — содействие коммуникации и оперативной совместимости. А такая простая вещь, как именование, стала главной причиной путаницы в сообществе.
Вспомните, что было сказано в 2012 году: «HTTP/2.0 означает только то, что формат не совместим по транспорту с HTTP/1.х». IETF последовал этому прецеденту. После долгих обсуждений перед и во время конференции IETF 103 всё-таки был достигнут консенсус о переименовании «HTTP over QUIC» в HTTP/3.
Мир стал лучше, и мы можем перейти к более важным дискуссиям.
Иногда названия документов могут сбивать с толку. Вот документы HTTP, описывающие синтаксис и семантику:
- RFC 7230 — Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing
- RFC 7231 — Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
По таким названиям можно предположить, что фундаментальная семантика HTTP специфична для конкретной версии HTTP, то есть HTTP/1.1. Но это случайный побочный эффект семейного дерева HTTP. Хорошая новость в том, что рабочая группа HTTPbis пытается решить проблему. Некоторые отважные члены WG начали ещё один раунд пересмотра документа. Эта работа ведётся прямо сейчас и известна как работа HTTP Core (возможно, вы слышали об этой рабочей группе под названиями HTTPtre или HTTPter: здесь тоже всё неоднозначно)Их усилия позволят сжать шесть черновиков до трёх:
- HTTP Semantics (draft-ietf-httpbis-semantics)
- HTTP Caching (draft-ietf-httpbis-caching)
- HTTP/1.1 Message Syntax and Routing (draft-ietf-httpbis-messaging)
В рамках этой новой структуры становится более очевидным, что HTTP/2 и HTTP/3 являются синтаксическими определениями для общей семантики HTTP. Это не означает, что у них нет собственных функций за пределами синтаксиса, но это должно помочь в дальнейшем обсуждении.
Эта статья поверхностно описала процесс стандартизации HTTP в IETF за последние три десятилетия. Особо не касаясь технических деталей, я попытался объяснить, как мы сейчас пришли к HTTP/3. Если вы пропустили середину и ищете суть в одной фразе, то вот она: HTTP/3 — это просто новый синтаксис HTTP, который работает на IETF QUIC, мультиплексированном и безопасном транспорте на основе UDP. Здесь много интересных технических нюансов, но придётся отложить их на другой раз.
Мы рассмотрели важные этапы в разработке HTTP и TLS, но отдельно друг от друга. Сейчас в конце статьи ещё раз публикуем полную кладограмму. Вы можете спокойно и тщательно изучить её в комфортной обстановке. И для суперсыщиков: вот абсолютно полная версия, включая черновики.
Введение в REST API — RESTful веб-сервисы / Habr
Эта статья представляет собой введение в RESTful веб-сервисы и краткий обзор REST и HTTP.Она начинает серию постов о разработке REST API:
- Введение в REST API — RESTful веб-сервисы
- Различия REST и SOAP
- Разработка REST API — что такое Contract First (контракт в первую очередь)?
- Разработка REST API — что такое Code First (код в первую очередь)?
- REST API — Что такое HATEOAS?
- Рекомендации по REST API — примеры проектирования веб-сервисов на Java и Spring
REST означает REpresentational State Transfer (Википедия: «передача состояния представления»). Это популярный архитектурный подход для создания API в современном мире.
Вы изучите:
- Что такое REST?
- На чем основан REST API?
- Как используется HTTP при создании REST API?
- Что такое ресурс?
- Как вы определяете ресурсы REST API?
- Каковы лучшие практики при разработке REST API?
Что такое REST?
REST расшифровывается как REpresentational State Transfer. Это был термин, первоначально введен Роем Филдингом (Roy Fielding), который также был одним из создателей протокола HTTP. Отличительной особенностью сервисов REST является то, что они позволяют наилучшим образом использовать протокол HTTP. Теперь давайте кратко рассмотрим HTTP.
Краткий обзор HTTP
Давайте сначала откроем браузер и зайдем на веб-страницу:
А затем щелкните на одной из страниц результатов:
Далее мы можем нажать на ссылку на странице, на которой мы оказались:
И перейти на другую страницу:
Вот как мы обычно просматриваем веб страницы.
Когда мы просматриваем страницы в Интернете, за кулисами происходит много вещей. Ниже приведено упрощенное представление о том, что происходит между браузером и серверами, работающими на посещаемых веб-сайтах:
Протокол HTTP
Когда вы вводите в браузере URL-адрес, например www.google.com, на сервер, указанный по URL-адресу, отправляется запрос на сервер. Затем этот сервер формирует и выдает ответ. Важным является формат этих запросов и ответов. Эти форматы определяются протоколом HTTP — Hyper Text Transfer Protocol.
Когда вы набираете URL в браузере, он отправляет запрос GET на указанный сервер. Затем сервер отвечает HTTP-ответом, который содержит данные в формате HTML — Hyper Text Markup Language. Затем браузер получает этот HTML-код и отображает его на экране.
Допустим, вы заполняете форму, присутствующую на веб-странице, со списком элементов. В таком случае, когда вы нажимаете кнопку «Submit» (Отправить), HTTP-запрос POST отправляется на сервер.
HTTP и RESTful веб-сервисы
HTTP обеспечивает базовый уровень для создания веб-сервисов. Поэтому важно понимать HTTP. Вот несколько ключевых абстракций.
Ресурс
Ресурс — это ключевая абстракция, на которой концентрируется протокол HTTP. Ресурс — это все, что вы хотите показать внешнему миру через ваше приложение. Например, если мы пишем приложение для управления задачами, экземпляры ресурсов будут следующие:
- Конкретный пользователь
- Конкретная задача
- Список задач
URI ресурса
Когда вы разрабатываете RESTful сервисы, вы должны сосредоточить свое внимание на ресурсах приложения. Способ, которым мы идентифицируем ресурс для предоставления, состоит в том, чтобы назначить ему URI — универсальный идентификатор ресурса. Например:
- Создать пользователя: POST /users
- Удалить пользователя: DELETE /users/1
- Получить всех пользователей: GET /users
- Получить одного пользователя: GET /users/1
REST и Ресурсы
Важно отметить, что с REST вам нужно думать о приложении с точки зрения ресурсов:
Определите, какие ресурсы вы хотите открыть для внешнего мира
Используйте глаголы, уже определенные протоколом HTTP, для выполнения операций с этими ресурсами.
Вот как обычно реализуется служба REST:
- Формат обмена данными: здесь нет никаких ограничений. JSON — очень популярный формат, хотя можно использовать и другие, такие как XML
- Транспорт: всегда HTTP. REST полностью построен на основе HTTP.
- Определение сервиса: не существует стандарта для этого, а REST является гибким. Это может быть недостатком в некоторых сценариях, поскольку потребляющему приложению может быть необходимо понимать форматы запросов и ответов. Однако широко используются такие языки определения веб-приложений, как WADL (Web Application Definition Language) и Swagger.
REST фокусируется на ресурсах и на том, насколько эффективно вы выполняете операции с ними, используя HTTP.
Компоненты HTTP
HTTP определяет следующую структуру запроса:
- строка запроса (request line) — определяет тип сообщения
- заголовки запроса (header fields) — характеризуют тело сообщения, параметры передачи и прочие сведения
- тело сообщения (body) — необязательное
HTTP определяет следующую структуру ответного сообщения (response):
- строка состояния (status line), включающая код состояния и сообщение о причине
- поля заголовка ответа (header fields)
- дополнительное тело сообщения (body)
Методы HTTP-запроса
Метод, используемый в HTTP-запросе, указывает, какое действие вы хотите выполнить с этим запросом. Важные примеры:
- GET: получить подробную информацию о ресурсе
- POST: создать новый ресурс
- PUT: обновить существующий ресурс
- DELETE: Удалить ресурс
Код статуса ответа HTTP
Код состояния всегда присутствует в ответе HTTP. Типичные примеры:
- 200 — успех
- 404 — cтраница не найдена
По этому вопросу имеется авторское видео.
Резюме
В статье приведен на верхнем уровне обзор архитектурного стиля REST. Подчеркивается тот факт, что HTTP является основным строительным блоком REST сервисов. HTTP — это протокол, который используется для определения структуры запросов и ответов браузера. Мы видели, что HTTP имеет дело главным образом с ресурсами, доступными на веб-серверах. Ресурсы идентифицируются с помощью URI, а операции над этими ресурсами выполняются с использованием глаголов, определенных протоколом HTTP.
Наконец, мы рассмотрели, как службы REST наилучшим образом используют функции, предлагаемые HTTP, для предоставления ресурсов внешнему миру. REST не накладывает никаких ограничений на форматы представления ресурсов или на определение сервиса.
Дополнительное чтение
Foundations of RESTful Architecture
Developing REST APIs
Построение систем доставки видео на основе HTTP Dynamic Streaming от Adobe и OpenSource / Habr
В рамках проекта для одного из наших заказчиков в очередной раз встала задача построить систему конвертации/ хранения/ доставки видео в интернет. Типичная такая задача создания своего маленького (или не очень маленького) “Тьюба” только с профессиональным, а не UGC-контентом.С момента создания первых “Тьюбов” технологии видео в интернете прошли некоторый путь развития, позволяют сейчас делать намного больше, да и требования к современному видео-сайту стали несколько иными.
Наиболее интересными трендами последнего времени, на наш взгляд, являются:
- возможность смотреть один видео-сайт с разных устройств,
- технология адаптивного HTTP стриминга
В результате появления и бурного распространения в последнее время мобильных устройств, реально удобных для потребления интернета с них, а также развития беспроводных технологий передачи данных, становится ясным, что нужно иметь вторую версию сайта, оптимизированную для мобильных iOS, Android и др. платформ. Третья версия сайта, оптимизированная под “10-ти футовый интерфейс”, скоро понадобится, когда станет популярной какая-либо технология WebTV, например GoogleTV.
Все это вписывается в т.н. концепцию “трех экранов”, с которого люди будут потреблять видео (и вообще интернет-контент) в ближайшем будущем — мобильник(планшет) в дороге, PC в офисе на работе, TV в гостиной дома.
Про технологию адаптивного HTTP стриминга хотелось бы поговорить поподробнее, что и является предметом данной статьи.
Сеть интернет по своей природе плохо подходит для доставки видео, особенно в реальном времени. С одной стороны мы хотим видеть плавный непрерывный поток видео, с другой — имеем нестабильное соединение с плавающими во времени характеристиками и бороться с этим можно двумя способами — увеличением задержки (буфера) или адаптаций битрейта потока.
Основная идея технологии адаптивного мультибитрейтного стриминга заключается как раз в адаптации потока — в том, что мы один ролик кодируем в нескольких битрейтах и стримим пользователю тот битрейт, который считаем возможным в данный момент времени, например, исходя из оценки текущей пропускной способности сети пользователя и оценки скорости декодирования (т.е. справляется ли компьютер пользователя с декодированием потока в реальном времени).
Прежде всего, это важно для сервисов прямых трансляций, когда пользователю важнее “не отставать от потока”, т.е., минимизируя вероятность возникновения “пребуферизации”, пусть даже временами жертвуя качеством картинки. Однако для для сервисов видео-по-запросу такая технология также крайне полезна — приятно ведь, когда видео стартует быстро, в том качестве, которое позволяет канал и всеми силами пытается не запинаться.
На практике это означает, что мы можем значительно улучшить восприятие сервиса не только пользователям с нестабильным/слабым каналом, где-нибудь глубоко в регионах, но и пользователям wifi-сетей, пользователям, у которых одно соединение является общим для нескольких пользователей в домохозяйстве и т.д. Для пользователей с выделенным качественным каналом данная технология просто автоматически определит скорость его канала и будет отдавать видео в подходящем битрейте — т.е. конечному пользователю больше не нужно знать о том, что такое 360p, 240p или SD, HD и т.д. — все происходит автоматически.
Расплачиваться за все эти преимущества приходится 3-мя вещами —
- усложнением процедуры стриминга,
- дополнительными затратами на кодирование,
- дополнительными затратами на хранение.
Первая причина на данный момент уже не должна приниматься во внимание, поскольку уже есть готовые opensource — кирпичики для строительства таких систем, о чем я дальше и расскажу.
Вторая и третья причины, конечно, важны, но тут разработчики сайта должны сами посчитать стоят ли их пользователи этих дополнительных затрат.
На данный момент существует, как минимум, три известные мне реализации технологии адаптивного мультибитрейтного стриминга:
- Apple HTTP Adaptive Streaming for iPhone/iPad,
- Microsoft Smooth Streaming for Silverlight,
- Adobe Dynamic Streaming for Flash.
Для практики разработки видео-сайтов наиболее важным, конечно, является реализация от Adobe, поскольку Apple HTTP Adaptive Streaming работает только для iOS устройств и Safari под MacOS X (хотя мне на днях показали один STB, в котором данный протокол реализован), а Silverlight, скажем так, пока не получил такой популярности как Flash.
Adobe реализовала Dynamic Streaming в рамках rtmp протокола уже довольно давно и только относительно недавно (с появлением flash 10.1) стало возможным использовать HTTP стриминг. Это очень важный шаг, поскольку раньше для использования динамического стриминга нужен был специализированный стриминговый сервер, теперь же бОльшая часть работы перенесена на клиент, а серверная поддержка упрощается вплоть до отдачи обычной HTTP статики.
Фактически нам нужно закодировать ролик в нескольких битрейтах, а дальше, либо нарезать на фрагменты, например, секунд по 5 и положить под быстрый сервер отдачи статики (см. рисунок ниже), либо, если существует сервер или стриминг-модуль, который из mp4 файликов может вырезать нужные фрагменты на лету, тогда на storage-уровень ставим его, а запросы маршрутизируем через какой-либо эффективный кешер. Более того, данный кешер может быть у провайдера CDN услуги. Одним из основных достоинств технологии адаптивного HTTP стриминга и является простота использования внешних CDN и кешеров — можно не заботится о преднаполнении кеша — в случае “cache miss” запрос проксируется на origin-server, одновременно сохраняясь в кеше.
Кеширование получается очень эффективным, поскольку в кеше прокси кусочками “оседает” востребованный контент. Причем эти кусочки относительно небольшие и можно придумывать различные стратегии управления кешем — когда “сохранять” кусочек, когда его удалять и т.д. Это дает большую свободу для разработки механизмов оптимизации разработчикам CDN сервисов. В свое время для первых версий системы доставки рутюба мы разрабатывали похожий механизм “кусочного” кеширования, позволивший долгое время проекту эффективно доставлять видео при минимуме оборудования.
С точки зрения программирования для поддержки HTTP Dynamic Streaming ребята из Adobe сделали одну простую вещь — у объекта NetStream появился метод appendBytes. Формат входного массива — байтпоток в FLV-формате. Фактически это дает возможность проигрывать байтпоток, а вопросы его доставки — отдельная задача. Например, можно доставлять эти байты посредством HTTP — кусочков и получится HTTP стриминг.
Системы от Apple и Microsoft реализуют систему доставки и проигрывания внутри своего “черного ящика”, а Adobe дает возможность программировать систему самостоятельно. Сделали они и открытую реализацию такой системы в рамках своего Open Source Media Framework. OSMF — это набор базовых классов, упрощающих написание видео-плейеров на ActionScript3, который, в том числе, включает реализацию поддержки HTTP динамического стриминга. Более того, спецификации данного протокола и подробности реализации Adobe старается раскрывать. Посмотреть можно тут и тут. Можете себе такое представить раньше, когда у Flash не было конкурентов и их будущее представлялось совершенно безоблачным?
Итак, возвращаемся к постановке задачи — мы хотим сделать видеохостинг, десктоп-версия будет использовать flash и технологию HTTP adaptive streaming.
Как собрать такую систему конвертации и доставки видео?
Кодировать будем в mp4, кодеки — x264 и faac, инструменты — ffmpeg, mencoder. Коммерческий софт мы не очень любим, если есть бесплатные альтернативы.
На данный момент мне известно о следующих реализациях данной технологии:
- коммерческий софт. Коммерческие сервера от Adobe и Wowza имеют реализацию данной технологии, в качестве основы для плейера можно взять OSMF. Вариант, наверное, хороший, но дорогой.
- есть свободная, но закрытая реализация от самой Adobe. Представляет собой перепаковщик исходных файлов в некий f4f-формат и модуль для apache, работающий с такими перепакованными файлами. Минусы — не получается работать с mp4-файликами, создаваемыми ffmpeg, поскольку исходники закрыты, понять почему — проблема.
- USP от CodeShop. Плюсы — прекрасная открытая реализация серверной части, минусы — закрыта клиентская и, вообще-то, софт коммерческий, хоть и OpenSource. Если сайт, использующий технологию, коммерческий — показывает рекламу или взимает плату за просмотр, нужно покупать лицензии.
Я работаю в компании, которая занимается видео-технологиями в интернет уже лет 10 и у нас есть определенный опыт и, посмотрев на документацию протоколов Adobe HTTP Dynamic Streaming, мы решили, что для проекта нашего “Тюба” нам проще и быстрее реализовать серверную поддержку самостоятельно. А клиентская реализация протокола в OSMF открыта и под BSD-лицензией.
Результатом является проект OpenHttpStreamer, который мы решили выложить в OpenSource под LGPL.
Официальная страничка проекта — http://inventos.ru/OpenHttpStreamer
Исходники доступны на GitHub — https://github.com/inventos/OpenHttpStreamer.
Мы пробовали собирать под Ubuntu 10.10, Fedora 12, Debian(Squeeze). Из особенностей — нужны scons, g++ версии 4.3.0 и выше и boost >=1.39.
Как пользоваться:$ git clone https://github.com/inventos/OpenHttpStreamer.git
$ cd OpenHttpStreamer/mp4frag
$ scons configure && scons
$ sudo scons install
Если все прошло успешно в /usr/local/bin/mp4frag будет собранная утилита создания статических фрагментов
$ mp4frag
Allowed options:
--help produce help message
--src arg source mp4 file name
--video_id arg (=some_video) video id for manifest file
--manifest arg (=manifest.f4m) manifest file name
--fragmentduration arg (=3000) single fragment duration, ms
--template make template files instead of full fragments
--nofragments make manifest only
Закодируем ffmpeg’ом какой-нибудь ролик в двух качествах — 400 и 700 кбит/сек (примерно)
$ ffmpeg -y -i test.mpg -acodec libfaac -ac 2 -ab 96k -ar 44100 -vcodec libx264 -vpre medium -g 100 -keyint_min 50 -b 300k -bt 300k -threads 2 test-q1.mp4
$ ffmpeg -y -i test.mpg -acodec libfaac -ac 2 -ab 96k -ar 44100 -vcodec libx264 -vpre medium -g 100 -keyint_min 50 -b 600k -bt 600k -threads 2 test-q2.mp4
Получили два mp4 файлика — test-q1.mp4 и test-q2.mp4, из которых генерируем статические фрагменты:
$ mp4frag --src test-q1.mp4 --src test-q2.mp4 --manifest=test.f4m
Результатом работы является описатель файла (“манифест”) — test.f4m и статические файлики-фрагменты в папках 0/ и 1/
Выкладываем test.f4m 0/ 1/ под DocRoot любого веб-сервера, способного отдавать статику, и нам остается написать на флеше простой плейер, используя в качестве движка OSMF, или взять готовый плейер.
Для быстрого теста можно воспользоваться нашей сборкой OSMF-плейера.
Для этого
1. под DocRoot нашего сервера (там же, где и test.f4m) помещаем такой crossdomain.xml:<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="inventos.ru" />
</cross-domain-policy>
2. переходим в браузере по ссылке http://inventos.ru/OpenHttpStreamer?url=http://your_http_host/test.f4m
Как обычно, если что-то не получается, смотрим логи нашего сервера — есть ли обращения от плейера к crossdomain.xml, test.f4m, файликам сегментов. Удобно проверять, все ли верно — самим «подергать» нужные адреса —wget -O - -S «http://your_http_host/test.f4m»
wget -O - -S «http://your_http_host/1/Seg1Frag1»
В заключение пару слов о том, что сейчас лежит в репозитарии. Пока написан только статический перепаковщик — mp4frag. Модуль для nginx в разработке. Мы уже продумали архитектуру и алгоритмистику, активно программируем и собираемся выпустить буквально на этой-следующей неделе — надеюсь, я по этому поводу еще напишу.
Модуль динамической генерации нам нужен, чтобы контент хранить в первозданном (mp4 после конвертации ffmpeg) виде, поскольку это достаточно универсальный формат, подходящий для других целей (стриминга на другие платформы). Есть интересный вариант — использование fragmented mp4, но он менее универсален.
Мы придумали простой способ — проиндексировать mp4 для быстрого доступа к нужным фрагментам и положить индексы в отдельном файлике рядом с самим контентом. Размер индекса будет всего около 1% от исходных файлов. Из-за того, что даже получив быстрый доступ к нужному фрагменту mdat в исходном mp4, нам нужно еще перемикшировать данные, добавив flv — заголовки ( особенность реализации OSMF), мы теряем в производительности по сравнению со статикой. Однако, проксируя запросы на данный модуль через быстрый web-cache и кешируя ответы, мы достигаем как высокой производительности, так и большой универсальности.
готовимся к переходу / Selectel corporate blog / Habr
В прошлом году в мире сетевых технологий произошло очень важное событие: была утверждена и стандартизирована новая версия протокола 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-соединения:
В современных браузерах количество одновременных 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 h3 http/1.1 # for a http server Protocols h3c 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 в течение какого-то времени, но уже сейчас вы можете принять меры по оптимизации, которые облегчат вам жизнь в будущем.
Полезные ссылки
В заключение приведём для заинтересованных читателей несколько полезных ссылок по теме:
Читателей, которые по тем или иным причинам не могут оставлять комментарии здесь, приглашаем в наш блог.