HTTP по UDP — используем с пользой протокол QUIC



    QUIC (Quick UDP Internet Connections) — это протокол поверх UDP, поддерживающий все возможности TCP, TLS и HTTP/2 и решающий большинство их проблем. Его часто называют новым или «экспериментальным» протоколом, но он уже давно пережил стадию эксперимента: разработка ведётся более 7 лет. За это время протокол не успел стать стандартом, но всё же получил широкое распространение. Например, QUIC используют для ускорения трафика и снижения задержек в мобильных сетях такие гиганты как Google и Facebook, а IETF объявила свой форк протокола основой для стандарта HTTP/3 (при том, что HTTP/2 использует только 44.8% сайтов).

    Концепция


    QUIC разрабатывался как замена устаревшего TCP, который изначально был заточен под проводные сети с низким процентом потерь. TCP доставляет пакеты по порядку, поэтому при потере одного пакета встаёт вся очередь (head-of-line blocking), что негативно сказывается на качестве и стабильности соединения. Чтобы избежать массовых потерь, сотовые сети прибегают к использованию больших буферов, что в свою очередь приводит к избыточности и false negative реакции протокола (bufferbloat). Кроме того, TCP тратит очень много времени на установление соединения: SYN/ACK и TLS запросы идут раздельно, требуя трёх roundtrip'ов вместо одного, как это делает QUIC.



    Так как QUIC сочетает в себе замену TCP и реализацию TLS 1.3, все соединения всегда зашифрованы, расшифровать такой трафик не проще чем если бы он шёл по HTTPS. Кроме того, QUIC реализован на прикладном уровне, как как полная замена TCP стека заняла бы вечность.

    Несмотря на поддержку мультиплексирования в HTTP/2, проблема head-of-line blocking там осталась из-за необходимости доставлять пакеты по порядку. QUIC реализован поверх UDP, поэтому у него блокировок не бывает в принципе, а чтобы пакеты не терялись безвозвратно, они нумеруются и могут содержать в себе части «соседей», обеспечивая избыточность. Кроме того, QUIC разбивает монолитную очередь на несколько потоков для разных типов запросов внутри одного соединения. Таким образом, при потере пакета проблемы могут возникнуть только у одной очереди (например, на передачу конкретного файла):

    image

    Использование


    Изначально QUIC разрабатывался внутри Google и был во многом заточен под использование внутри компании. В 2013 году его передали в IETF для стандартизации (которая идёт до сих пор), и теперь каждый может поучаствовать в развитии протокола, предложив то, чего не хватает именно ему. Рабочая группа IETF ежегодно организует встречи, в рамках которых утверждается новый стандарт и ведётся обсуждение нововведений. Эта реализация QUIC считается основной и именно на её основе сертифицируется стандарт HTTP/3.

    Пока что об включении HTTP/3 как основного протокола речь не идёт, потому что он ещё не закончен и почти не поддерживается:



    Но QUIC можно реализовать как транспорт между приложением и сервером, что успешно проделали в Uber:

    Комментарий Uber о внедрении QUIC


    Чтобы успешно встроить QUIC и улучшить производительность приложения в условиях плохой связи, мы заменили старый стек (HTTP/2 поверх TLS/TCP) на протокол QUIC. Мы задействовали сетевую библиотеку Cronet из Chromium Projects, которая содержит оригинальную, гугловскую версию протокола – gQUIC. Эта реализация также постоянно совершенствуется, чтобы следовать последней спецификации IETF.

    Сперва мы интегрировали Cronet в наши Android-приложения, чтобы добавить поддержку QUIC. Интеграция была осуществлена так, чтобы максимально снизить затраты на миграцию. Вместо того, чтобы полностью заменить старый сетевой стек, который использовал библиотеку OkHttp, мы интегрировали Cronet ПОД фреймворком OkHttp API. Выполнив интеграцию таким способом, мы избежали изменений в наших сетевых вызовах (который используют Retrofit) на уровне API.

    Подобно подходу к Android-устройствам, мы внедрили Cronet в приложения Uber под iOS, перехватывая HTTP-трафик из сетевых API, используя NSURLProtocol. Эта абстракция, предоставленная iOS Foundation, обрабатывает протокол-специфичные URL-данные и гарантирует, что мы можем интегрировать Cronet в наши iOS-приложения без существенных миграционных затрат.
    взято из этого перевода статьи Uber

    На бэкенде они ловили QUIC-соединения через Google Cloud lb, который поддерживает протокол с середины 2018 года.

    Неудивительно, что Google Cloud прекрасно работает с протоколом, разработанным Google, но какие есть альтернативы?

    Nginx


    Не так давно CloudFlare пробовала скрестить nginx (который по умолчанию не умеет HTTP/3) со своим инструментом Quiche. Реализация доступна в виде единственного .patch файла, к которому прилагается туториал по установке:

    curl -O https://nginx.org/download/nginx-1.16.1.tar.gz
    tar xvzf nginx-1.16.1.tar.gz
    git clone --recursive https://github.com/cloudflare/quiche
    cd nginx-1.16.1
    patch -p01 < ../quiche/extras/nginx/nginx-1.16.patch

    Здесь можно подключить свои модули при необходимости

    ./configure                          	\
       	--prefix=$PWD                       	\
       	--with-http_ssl_module              	\
       	--with-http_v2_module               	\
       	--with-http_v3_module               	\
       	--with-openssl=../quiche/deps/boringssl \
       	--with-quiche=../quiche
     make

    Остаётся только включить поддержку HTTP/3

    events {
        worker_connections  1024;
    }
    
    http {
        server {
            # Enable QUIC and HTTP/3.
            listen 443 quic reuseport;
    
            # Enable HTTP/2 (optional).
            listen 443 ssl http2;
    
            ssl_certificate      cert.crt;
            ssl_certificate_key  cert.key;
    
            # Enable all TLS versions (TLSv1.3 is required for QUIC).
            ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    
            # Request buffering in not currently supported for HTTP/3.
            proxy_request_buffering off;
    
            # Add Alt-Svc header to negotiate HTTP/3.
            add_header alt-svc 'h3-27=":443"; ma=86400';
        }
    }

    В обычных браузерах соединиться по HTTP/3 пока не получится, но можно взять Chrome Canary и запустить его с флагом --enable-quic, обратиться к своему серверу или, например, сайту quic.rocks и посмотреть тип соединения в Developer Tools:

    Вместо HTTP/3 пишется http2+quic/99, но это по сути одно и то же.

    Другие технологии



    Заключение




    Интерес к QUIC нестабильно, но растёт, ведётся работа над его стандартизацией. Новые реализации протокола появляются уже чуть ли не каждый месяц, и с каждым годом всё больше разработчиков убеждаются, что будущее за QUIC. Допускается даже включение протокола в будущие версии TCP стека, а это означает, что рано или поздно весь интернет переедет на более устойчивые и быстрые соединения.

    Уже сейчас вы можете настроить QUIC-взаимодействие для своей инфраструктуры или даже отдавать его браузерам — они все планируют добавить поддержку протокола, и печальная статистика с caniuse станет веселее.



    VDSina.ru — хостинг серверов
    Серверы в Москве и Амстердаме от 11 рублей в день

    Комментарии 8

      +2

      Цифр не хватает, какая разница по скорости на практике получается.

        0
        На с++ нет еще готовых библиотек для QUIC или http/3?
        Чтобы встроить в свое приложение и в клиенте и в сервере, и получить замену TCP-сокетам?
          0

          Пока вот только сишная либа msquic

            0
            msquic я глянул, но смутило windows 10 only
          0

          В чем преимущества перед keep-alive?

            +2
            Разница между шутками про TCP и про UDP в том, что шутки про UDP не до всех доходят
              0
              Я понимаю разницу. И понимаю что тройное рукопожатие отнимает много времени. Но после установки соединения какая разница?
                +1
                в статье же написано, при ненадежном соединении «при потере одного пакета встаёт вся очередь»

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

          Самое читаемое