Протокол QUIC (название расшифровывается как Quick UDP Internet Connections) — совершенно новый способ передачи информации в интернете, построенный поверх протокола UDP, вместо общепринятого ранее использования TCP. Некоторые люди называют его (в шутку) TCP/2. Переход к UDP — наиболее интересная и мощная особенность протокола, из которой следуют некоторые другие особенности.
Сегодняшний Web построен на протоколе TCP, который был выбран за его надёжность и гарантированность доставки пакетов. Для открытия TCP-соединения используется так называемое «трёхкратное рукопожатие». Это означает дополнительные циклы отправки-приёма сообщений для каждого нового соединения, что увеличивает задержки.
Если вы захотите установить защищённое TLS-соединение, придётся переслать ещё больше пакетов.
Некоторые инновации, вроде TCP Fast Open, улучшат некоторые аспекты ситуации, но эта технология пока не очень широко распространена.
Протокол UDP, с другой стороны, построен на идее «отправить пакет и забыть о нём». Сообщение, отправленное по UDP, будет доставлено получателю (не гарантированно, с некоторой вероятностью успеха). Яркое преимущество здесь в меньшем времени установки соединения, такой же яркий недостаток — негарантированность доставки или порядка прихода пакетов получателю. Это означает, что для обеспечения надёжности придётся построить некоторый механизм поверх UDP, который гарантирует доставку пакетов.
И здесь на сцену выходит QUIC от Google.
Протокол QUIC может открыть соединение и согласовать все параметры TLS (HTTPs) за 1 или 2 пакета (1 или 2 — зависит от того, открывается ли соединение к новому серверу или к уже знакомому).
Это невероятно ускоряет открытие соединения и начало загрузки данных.
Планы команды разработчиков протокола QUIC выглядят очень амбициозно: протокол попытается совместить скорость UDP с надёжностью TCP.
Вот что об этом пишет Википедия:
В этой цитате есть важный момент: если QUIC докажет свою эффективность, то есть шанс, что опробованные в нём идеи станут частью следующей версии TCP.
Протокол TCP достаточно сильно формализован. Его реализации есть в ядрах Windows и Linux, в каждой мобильной OS, да и во многих более простых устройствах. Улучшение TCP является непростым делом, поскольку все эти реализации должны его поддерживать.
UDP же является относительно простым протоколом. Значительно быстрее разработать новый протокол поверх UDP чтобы иметь возможность проверить теоретические идеи, работу в перегруженных сетях, обработку заблокированных потерянным пакетом потоков и т.д. Как только эти моменты будут прояснены — можно будет начинать работу по переносу лучших частей QUIC в следующую версию TCP.
Если вы посмотрите на уровни, составляющие современное HTTPs-соединение, то увидите, что QUIC заменяет собой весь TLS-стек и часть HTTP/2.
Да, протокол QUIC реализует собственный крипто-слой, что позволяет избежать использования TLS 1.2.
Поверх QUIC работает небольшая прослойка HTTP/2 API, используемая для общения с удалёнными серверами. Она меньше полной реализации HTTP/2, поскольку мультиплексирование и установка соединения уже реализованы в QUIC. Остаётся лишь реализация протокола HTTP.
Протоколы SPDY и HTTP/2 используют одно TCP-соединение с сервером вместо отдельных соединений для каждой страницы. Это единое соединение может быть использовано для независимых запросов и получения отдельных ресурсов.
Поскольку весь обмен данными теперь построен на одном TCP-соединении, мы автоматически получаем один недостаток: блокировку начала очереди (Head-of-line blocking). В протоколе TCP требуется, чтобы пакеты приходили (точнее обрабатывались) в правильном порядке. Если пакет потерялся на пути к\от сервера — он должен быть отослан повторно. TCP-соединение в это время должно ожидать (блокироваться) и лишь после повторного получения потерянного пакета продолжается обработка всех пакетов в очереди — только так можно соблюсти условие корректного порядка обработки пакетов.
Протокол QUIC решает эту проблему фундаментально — отказом от протокола TCP в пользу UDP, который не требует соблюдения порядка обработки принимаемых пакетов. И, хотя потери пакетов, конечно, всё так же возможны, это будет влиять только на обработку тех ресурсов (индивидуальных HTML\CSS\JS-файлов), к которым относится потерянный пакет.
QUIC очень элегантно комбинирует лучшие части SPDY\HTTP2 (мультиплексирование) с неблокируемым транспортным протоколом.
Если у вас быстрое Интернет-соединение, то задержки передачи пакетов между вашим компьютером и удалённым сервером составляют около 10-50 мс. Каждый пересылаемый от вас по сети пакет будет получен сервером через этот промежуток времени. Для такого порядка величин преимущества QUIC могут быть не очень понятны. Но стоит нам рассмотреть вопрос обмена данными с сервером на другом континенте или использования мобильных сетей — и вот у нас уже появляются задержки порядка 100-150 мс.
В итоге на мобильном устройстве, при доступе к находящемуся далеко серверу, разница между 4 пакетами TCP+TLS и одним пакетом QUIC может составить около 300 мс, что уже является существенной величиной, наблюдаемой невооруженным глазом.
Изящной фичей протокола QUIC является превентивная коррекция ошибок (Forward Error Correction, FEC). Каждый пересылаемый пакет содержит в себе некоторое количество данных других пакетов, что позволяет реконструировать любой потерянный пакет по данным в его соседях, без необходимости запрашивать переотправку потерянного пакета и дожидаться его содержимого. Это, по сути, реализация RAID 5 на сетевом уровне.
Но вы уже и сами видите недостаток этого решения: каждый пакет становится немного больше. Текущая реализация устанавливает этот оверхед равным 10%, т.е. сделав каждый пересылаемый пакет на 10% больше мы тем самым получаем возможность восстановления данных без перезапроса в случае, если будет теряться не более каждого десятого пакета.
Эта избыточность — плата пропускной способностью сети за уменьшение задержек (что выглядит логично, ведь скорости соединения и пропускная способность каналов непрерывно растут, а вот тот факт, что передача данных на другой конец планеты занимает сотню миллисекунд — навряд ли удастся как-то изменить без фундаментального переворота в физике).
Ещё одной интересной особенностью использования протокола UDP является то, что вы больше не привязаны к IP сервера. В протоколе TCP соединение определяется четырьмя параметрам: IP-адресами сервера и клиента, портами сервера и клиента. В Linux вы можете увидеть эти параметры для каждого установленного соединения с помощью комманды netstat:
Если любой из этих четырёх параметров потребуется изменить — нам потребуется открывать новое TCP-соединение. Вот почему трудно поддерживать стабильную связь на мобильных устройствах при переключении между WiFi и 3G/LTE.
В QUIC, с его использованием UDP, данного набора параметров больше нет. QUIC вводит понятие идентификатора соединения, называемого Connection UUID. Появляется возможность перейти с WiFi на LTE с сохранением Connection UUID, таким образом избежав затрат на пересоздание соединения. Похожим образом работает Mosh Shell, сохраняя SSH-соединение активным при смене IP-адреса.
Также данный подход открывает двери возможности использования нескольких источников для запроса контента. Если Connection UUID может быть использовано для перехода от WiFi к мобильной сети, то мы можем, теоретически, использовать и их обе одновременно для получения данных параллельно. Больше каналов связи — больше пропускная способность.
Браузер Chrome имеет экспериментальную поддержку QUIC с 2014-го года. Если вы хотите потестировать QUIC, то можете включить его поддержку в Chrome и попробовать поработать с сервисами Google, которые его поддерживают. Это сильное преимущество Google — возможность использовать комбинацию своего браузера и своих же веб-ресурсов. Включив QUIC в самом популяром в мире браузере (Chrome) и высоконагруженных сайтах (Youtube.com, Google.com), они смогут получить большую, наглядную статистику использования протокола, что позволит выявить все существенные проблемы практического использования QUIC.
Есть плагин для Chrome, который показывает в виде иконки поддержку сервером протоколов HTTP/2 и QUIC.
Вы также можете увидеть открытые QUIC-соединения открыв вкладку chrome://net-internals/#quic прямо сейчас (обратите внимание в таблице на параметр Connection UUID, упомянутый ранее)
Вы можете пойти ещё дальше и посмотреть все открытые соединения и все переданные по ним пакеты: chrome://net-internals/#events&q=type:QUIC_SESSION%20is:active.
Если вы — сисадмин или сетевой инженер, то, возможно, слегка дёрнулись, когда услышали о том, что QUIC использует UDP вместо TCP. Да, наверное, у вас есть на то свои причины. Возможно у вас (как, например, и у нас в компании), настройки доступа к веб-серверу выглядят как-то так:
Самое главное здесь, конечно же, столбик протокола, в котором явно написано «TCP». Подобные настройки используются тысячами веб-серверов по всему миру, поскольку они разумны. 80 и 443 порты, только TCP — и больше ничего на продакшн-вебсервере разрешено быть не должно. Никакого UDP.
Ну, если мы хотим использовать QUIC, придётся добавить и разрешение UDP-соединений на 443-ий порт. В больших энтерпрайз-сетях это может быть проблемой. Как показывает статистика Google, UDP кое-где блокируется:
Эти цифры были получены в ходе недавнего исследования в Швеции. Отметим несколько ключевых моментов:
Преимущество шифрования по-умолчанию в том, что различные инструменты Deep Packet Inspection не могут расшифровать зашифрованную информацию и модифицировать данные, они видят бинарный поток и (хочется верить) просто пропускают его.
На данный момент QUIC поддерживается вебсервером Caddy (с версии 0.9). И клиентская, и серверная реализация QUIC ещё на стадии экспериментальной поддержки, так что будьте осторожны с практическим применением QUIC. Поскольку ни у кого по-умолчанию не включен QUIC, то, вероятно, будет безопасным включить его на своём сервере и экспериментировать со своим браузером (Обновление: с версии 52 QUIC включён по-умолчанию в Chrome).
В 2015-ом году Google опубликовала некоторые результаты замеров производительности QUIC.
Статистика Youtube особенно интересна. Если улучшения подобного масштаба действительно возможны, то мы увидим очень быструю адаптацию QUIC как-минимум в сфере видеосервисов вроде Vimeo, а также на рынке «видео для взрослых».
Лично я нахожу протокол QUIC совершенно очаровательным! Огромный объём работы, проделанный его разработчиками, не пропал даром — один лишь факт того, что уже сегодня крупнейшие сайты в Интернете поддерживают QUIC, немного ошеломляет. Я жду не дождусь финальной спецификации QUIC, ну и дальнейшей её реализации всеми браузерами и веб-серверами.
Больше информации по теме:
Сегодняшний Web построен на протоколе TCP, который был выбран за его надёжность и гарантированность доставки пакетов. Для открытия TCP-соединения используется так называемое «трёхкратное рукопожатие». Это означает дополнительные циклы отправки-приёма сообщений для каждого нового соединения, что увеличивает задержки.
Если вы захотите установить защищённое TLS-соединение, придётся переслать ещё больше пакетов.
Некоторые инновации, вроде TCP Fast Open, улучшат некоторые аспекты ситуации, но эта технология пока не очень широко распространена.
Протокол UDP, с другой стороны, построен на идее «отправить пакет и забыть о нём». Сообщение, отправленное по UDP, будет доставлено получателю (не гарантированно, с некоторой вероятностью успеха). Яркое преимущество здесь в меньшем времени установки соединения, такой же яркий недостаток — негарантированность доставки или порядка прихода пакетов получателю. Это означает, что для обеспечения надёжности придётся построить некоторый механизм поверх UDP, который гарантирует доставку пакетов.
И здесь на сцену выходит QUIC от Google.
Протокол QUIC может открыть соединение и согласовать все параметры TLS (HTTPs) за 1 или 2 пакета (1 или 2 — зависит от того, открывается ли соединение к новому серверу или к уже знакомому).
Это невероятно ускоряет открытие соединения и начало загрузки данных.
Зачем нужен QUIC?
Планы команды разработчиков протокола QUIC выглядят очень амбициозно: протокол попытается совместить скорость UDP с надёжностью TCP.
Вот что об этом пишет Википедия:
Улучшение протокола TCP является долговременной целью для Google, а протокол QUIC создан как эквивалент независимого TCP-соединения, но с уменьшенными задержками и улучшенной в духе SPDY поддержкой мультиплексирования. Если QUIC покажет свою эффективность, то эти возможности могут войти в следующую версию протоколов TCP и TLS (разработка которых занимает больше времени).
В этой цитате есть важный момент: если QUIC докажет свою эффективность, то есть шанс, что опробованные в нём идеи станут частью следующей версии TCP.
Протокол TCP достаточно сильно формализован. Его реализации есть в ядрах Windows и Linux, в каждой мобильной OS, да и во многих более простых устройствах. Улучшение TCP является непростым делом, поскольку все эти реализации должны его поддерживать.
UDP же является относительно простым протоколом. Значительно быстрее разработать новый протокол поверх UDP чтобы иметь возможность проверить теоретические идеи, работу в перегруженных сетях, обработку заблокированных потерянным пакетом потоков и т.д. Как только эти моменты будут прояснены — можно будет начинать работу по переносу лучших частей QUIC в следующую версию TCP.
Где же сегодня место QUIC?
Если вы посмотрите на уровни, составляющие современное HTTPs-соединение, то увидите, что QUIC заменяет собой весь TLS-стек и часть HTTP/2.
Да, протокол QUIC реализует собственный крипто-слой, что позволяет избежать использования TLS 1.2.
Поверх QUIC работает небольшая прослойка HTTP/2 API, используемая для общения с удалёнными серверами. Она меньше полной реализации HTTP/2, поскольку мультиплексирование и установка соединения уже реализованы в QUIC. Остаётся лишь реализация протокола HTTP.
Блокировка начала очереди (Head-of-line blocking)
Протоколы SPDY и HTTP/2 используют одно TCP-соединение с сервером вместо отдельных соединений для каждой страницы. Это единое соединение может быть использовано для независимых запросов и получения отдельных ресурсов.
Поскольку весь обмен данными теперь построен на одном TCP-соединении, мы автоматически получаем один недостаток: блокировку начала очереди (Head-of-line blocking). В протоколе TCP требуется, чтобы пакеты приходили (точнее обрабатывались) в правильном порядке. Если пакет потерялся на пути к\от сервера — он должен быть отослан повторно. TCP-соединение в это время должно ожидать (блокироваться) и лишь после повторного получения потерянного пакета продолжается обработка всех пакетов в очереди — только так можно соблюсти условие корректного порядка обработки пакетов.
Протокол QUIC решает эту проблему фундаментально — отказом от протокола TCP в пользу UDP, который не требует соблюдения порядка обработки принимаемых пакетов. И, хотя потери пакетов, конечно, всё так же возможны, это будет влиять только на обработку тех ресурсов (индивидуальных HTML\CSS\JS-файлов), к которым относится потерянный пакет.
QUIC очень элегантно комбинирует лучшие части SPDY\HTTP2 (мультиплексирование) с неблокируемым транспортным протоколом.
Почему уменьшить количество пересылаемых пакетов так важно
Если у вас быстрое Интернет-соединение, то задержки передачи пакетов между вашим компьютером и удалённым сервером составляют около 10-50 мс. Каждый пересылаемый от вас по сети пакет будет получен сервером через этот промежуток времени. Для такого порядка величин преимущества QUIC могут быть не очень понятны. Но стоит нам рассмотреть вопрос обмена данными с сервером на другом континенте или использования мобильных сетей — и вот у нас уже появляются задержки порядка 100-150 мс.
В итоге на мобильном устройстве, при доступе к находящемуся далеко серверу, разница между 4 пакетами TCP+TLS и одним пакетом QUIC может составить около 300 мс, что уже является существенной величиной, наблюдаемой невооруженным глазом.
Превентивная коррекция ошибок
Изящной фичей протокола QUIC является превентивная коррекция ошибок (Forward Error Correction, FEC). Каждый пересылаемый пакет содержит в себе некоторое количество данных других пакетов, что позволяет реконструировать любой потерянный пакет по данным в его соседях, без необходимости запрашивать переотправку потерянного пакета и дожидаться его содержимого. Это, по сути, реализация RAID 5 на сетевом уровне.
Но вы уже и сами видите недостаток этого решения: каждый пакет становится немного больше. Текущая реализация устанавливает этот оверхед равным 10%, т.е. сделав каждый пересылаемый пакет на 10% больше мы тем самым получаем возможность восстановления данных без перезапроса в случае, если будет теряться не более каждого десятого пакета.
Эта избыточность — плата пропускной способностью сети за уменьшение задержек (что выглядит логично, ведь скорости соединения и пропускная способность каналов непрерывно растут, а вот тот факт, что передача данных на другой конец планеты занимает сотню миллисекунд — навряд ли удастся как-то изменить без фундаментального переворота в физике).
Возобновление сессии и параллельные загрузки
Ещё одной интересной особенностью использования протокола UDP является то, что вы больше не привязаны к IP сервера. В протоколе TCP соединение определяется четырьмя параметрам: IP-адресами сервера и клиента, портами сервера и клиента. В Linux вы можете увидеть эти параметры для каждого установленного соединения с помощью комманды netstat:
$ netstat -anlp | grep ':443'
...
tcp6 0 0 2a03:a800:a1:1952::f:443 2604:a580:2:1::7:57940 TIME_WAIT -
tcp 0 0 31.193.180.217:443 81.82.98.95:59355 TIME_WAIT -
...
Если любой из этих четырёх параметров потребуется изменить — нам потребуется открывать новое TCP-соединение. Вот почему трудно поддерживать стабильную связь на мобильных устройствах при переключении между WiFi и 3G/LTE.
В QUIC, с его использованием UDP, данного набора параметров больше нет. QUIC вводит понятие идентификатора соединения, называемого Connection UUID. Появляется возможность перейти с WiFi на LTE с сохранением Connection UUID, таким образом избежав затрат на пересоздание соединения. Похожим образом работает Mosh Shell, сохраняя SSH-соединение активным при смене IP-адреса.
Также данный подход открывает двери возможности использования нескольких источников для запроса контента. Если Connection UUID может быть использовано для перехода от WiFi к мобильной сети, то мы можем, теоретически, использовать и их обе одновременно для получения данных параллельно. Больше каналов связи — больше пропускная способность.
Практические реализации QUIC
Браузер Chrome имеет экспериментальную поддержку QUIC с 2014-го года. Если вы хотите потестировать QUIC, то можете включить его поддержку в Chrome и попробовать поработать с сервисами Google, которые его поддерживают. Это сильное преимущество Google — возможность использовать комбинацию своего браузера и своих же веб-ресурсов. Включив QUIC в самом популяром в мире браузере (Chrome) и высоконагруженных сайтах (Youtube.com, Google.com), они смогут получить большую, наглядную статистику использования протокола, что позволит выявить все существенные проблемы практического использования QUIC.
Есть плагин для Chrome, который показывает в виде иконки поддержку сервером протоколов HTTP/2 и QUIC.
Вы также можете увидеть открытые QUIC-соединения открыв вкладку chrome://net-internals/#quic прямо сейчас (обратите внимание в таблице на параметр Connection UUID, упомянутый ранее)
Вы можете пойти ещё дальше и посмотреть все открытые соединения и все переданные по ним пакеты: chrome://net-internals/#events&q=type:QUIC_SESSION%20is:active.
Как при этом всём работают файрволы?
Если вы — сисадмин или сетевой инженер, то, возможно, слегка дёрнулись, когда услышали о том, что QUIC использует UDP вместо TCP. Да, наверное, у вас есть на то свои причины. Возможно у вас (как, например, и у нас в компании), настройки доступа к веб-серверу выглядят как-то так:
Самое главное здесь, конечно же, столбик протокола, в котором явно написано «TCP». Подобные настройки используются тысячами веб-серверов по всему миру, поскольку они разумны. 80 и 443 порты, только TCP — и больше ничего на продакшн-вебсервере разрешено быть не должно. Никакого UDP.
Ну, если мы хотим использовать QUIC, придётся добавить и разрешение UDP-соединений на 443-ий порт. В больших энтерпрайз-сетях это может быть проблемой. Как показывает статистика Google, UDP кое-где блокируется:
Эти цифры были получены в ходе недавнего исследования в Швеции. Отметим несколько ключевых моментов:
- Поскольку QUIC тестировался только с сервисами Google, можно предположить, что недоступности из-за неверно настроенного файрвола на сервере не было.
- Цифры отражают успешность исходящих запросов от пользователей на 443-ий UDP-порт.
- QUIC может быть отключен в Chrome по разным причинам. Держу пари, что в некоторых энтерпрайз-средах его отключили превентивно, просто на всякий случай.
- Поскольку протокол QUIC по-умолчанию использует шифрование, нам следует беспокоиться только о доступе к 443-му порту, доступность или недоступность 80-го не должна как-то влиять.
Преимущество шифрования по-умолчанию в том, что различные инструменты Deep Packet Inspection не могут расшифровать зашифрованную информацию и модифицировать данные, они видят бинарный поток и (хочется верить) просто пропускают его.
Использование QUIC на серверной стороне
На данный момент QUIC поддерживается вебсервером Caddy (с версии 0.9). И клиентская, и серверная реализация QUIC ещё на стадии экспериментальной поддержки, так что будьте осторожны с практическим применением QUIC. Поскольку ни у кого по-умолчанию не включен QUIC, то, вероятно, будет безопасным включить его на своём сервере и экспериментировать со своим браузером (Обновление: с версии 52 QUIC включён по-умолчанию в Chrome).
Производительность QUIC
В 2015-ом году Google опубликовала некоторые результаты замеров производительности QUIC.
Как и ожидалось, QUIC затмевает классический TCP на плохих каналах связи, давая выигрыш в полсекунды на загрузке стартовой страницы www.google.com на 1% наиболее медленных соединений. Этот выигрыш ещё более заметен на видеосервисах вроде YouTube. Пользователи на 30% меньше жаловались на задержки из-за буферизации при просмотре видео при использовании QUIC.
Статистика Youtube особенно интересна. Если улучшения подобного масштаба действительно возможны, то мы увидим очень быструю адаптацию QUIC как-минимум в сфере видеосервисов вроде Vimeo, а также на рынке «видео для взрослых».
Выводы
Лично я нахожу протокол QUIC совершенно очаровательным! Огромный объём работы, проделанный его разработчиками, не пропал даром — один лишь факт того, что уже сегодня крупнейшие сайты в Интернете поддерживают QUIC, немного ошеломляет. Я жду не дождусь финальной спецификации QUIC, ну и дальнейшей её реализации всеми браузерами и веб-серверами.
Комментарий к статье от Jim Roskind, одного из разработчиков QUIC
Я потратил много лет на исследования, дизайн и разработку реализации протокола QUIC, и хотел бы добавить к статье кое-какие свои мысли. В тексте был верно подмечен момент о вероятной недоступности протокола QUIC у некоторых пользователей из-за строгих корпоративных политик в отношении протокола UDP. Это и было причиной того, что мы получили среднюю доступность протокола на уровне в 93%.
Если мы вернёмся немного в прошлое, то увидим что ещё совсем недавно корпоративные системы часто запрещали даже исходящий трафик к 80-му порту, с аргументацией «это уменьшит количество времени, которое работники тратят на серфинг в ущерб работе». Позже, как вы знаете, преимущества доступа к веб-сайтам (в том числе в производственных целях) вынудило большинство корпораций пересмотреть свои правила, разрешив выход в интернет с рабочего места рядового сотрудника. Я ожидаю чего-то аналогичного и с протоколом QUIC: как-только станет понятно, что с новым протоколом связь может быть быстрее, задачи выполняются оперативнее — он пробьёт себе путь и в энтерпрайз.
Я рассчитываю, что QUIC массово заместит собой TCP, и это даже помимо того, что он подарит следующей версии TCP ряд своих идей. Дело в том, что TCP реализуется в ядрах операционных систем, в железе, а значит адаптация к новой версии может занять 5-15 лет, в то время как внедрить QUIC поверх общедоступного и всеми поддерживаемого UDP можно в отдельно взятом продукте\сервисе буквально за несколько недель или месяцев.
Больше информации по теме: