Поддержка push HTTP/2-сервера включена в NGINX Plus R15.

Они рады объявить, что NGINX 1.13.9 , выпущенный 20 февраля 2018 года, включает поддержку проталкивания HTTP/2-сервера.

Смотрите также http2 в nginx+

Push-сервер, который определен в спецификации HTTP/2 , позволяет серверу передавать ресурсы удаленному клиенту, ожидая, что клиент вскоре может запросить эти ресурсы. Таким образом, вы можете потенциально уменьшить количество RTT (время прохождения туда-обратно - время, необходимое для запроса и ответа) в операции загрузки страницы на один RTT или более, обеспечивая более быстрый ответ пользователю.

Server push можно использовать для заполнения клиента таблицами стилей (CSS), изображениями (JPG) и другими ресурсами (JS), которые ему понадобятся для отображения веб-страницы. Вы должны следить, чтобы передать только те ресурсы, которые необходимы. Не передавайте ресурсы, которые клиент уже кэшировал.

Содержание:

Настройка HTTP/2 Server Push

Чтобы передать ресурсы вместе с загрузкой страницы, используйте директиву http2_push следующим образом:

server {
    # Ensure that HTTP/2 is enabled for the server        
    listen 443 ssl http2;

    ssl_certificate ssl/certificate.pem;
    ssl_certificate_key ssl/key.pem;

    root /var/www/html;

    # whenever a client requests demo.html, also push
    # /style.css, /image1.jpg and /image2.jpg
    location = /demo.html {
        http2_push /style.css;
        http2_push /image1.jpg;
        http2_push /image2.jpg;
    }
}

Проверка HTTP/2 сервера Push

Вы можете легко проверить, что сервер работает, используя один из двух методов:

  • Инструменты разработчика в вашем веб-браузере
  • Клиент командной строки HTTP/2, такой как nghttp

Проверка Server Push с помощью инструментов разработчика (Google Chrome)

Вот как можно использовать инструменты разработчика в вашем веб-браузере, чтобы убедиться, что сервер работает, используя Google Chrome. На рисунке столбец «Initiator» на вкладке «Network» в инструментах разработчика Chrome указывает, что несколько ресурсов были переданы клиенту как часть запроса для /demo.html

Снимок экрана со вкладкой Сеть средства разработчика Chrome, показывающий, что для отправки трех ресурсов использовался сервер HTTP / 2 push
Столбец Initiator указывает, что для отправки ресурсов использовался сервер

Проверка с помощью клиента командной строки (nghttp)

В дополнение к инструментам веб-браузера вы можете использовать nghttp командной строки nghttp из проекта nghttp2.org, чтобы убедиться, что сервер работает. Вы можете скачать nghttp командной строки nghttp с GitHub или установить соответствующий пакет операционной системы, где он доступен. Для Ubuntu используйте пакет nghttp2-client.

В выводе звездочкой (*) отмечены ресурсы, которые были выдвинуты сервером.

$ nghttp -ans https://example.com/demo.html
id responseEnd requestStart process code size request path
13 +84.25ms +136us 84.11ms 200 492 /demo.html
2 +84.33ms * +84.09ms 246us 200 266 /style.css
4 +261.94ms * +84.12ms 177.83ms 200 40K /image2.jpg
6 +685.95ms * +84.12ms 601.82ms 200 173K /image1.jpg

Автоматическая передача ресурсов клиентам

Во многих ситуациях неудобно или даже невозможно перечислить ресурсы, которые вы хотите использовать, в файле конфигурации NGINX. По этой причине NGINX также поддерживает директиву о перехвате Link preload headers и последующей передаче ресурсов, указанных в этих заголовках. Чтобы включить предварительную загрузку, http2_push_preload в конфигурацию директиву http2_push_preload:

server {
    # Ensure that HTTP/2 is enabled for the server        
    listen 443 ssl http2;

    ssl_certificate ssl/certificate.pem;
    ssl_certificate_key ssl/key.pem;

    root /var/www/html;

    # Intercept Link header and initiate requested Pushes
    location = /myapp {
        proxy_pass http://upstream;
        http2_push_preload on;
    }
}

Например, когда NGINX работает как прокси-сервер (для HTTP, FastCGI или других типов трафика), вышестоящий сервер может добавить заголовок Link например, в свой ответ:

Link: </style.css>; as=style; rel=preload

NGINX перехватывает этот заголовок и запускает отправку сервером /style.css. Путь в заголовке Link должен быть абсолютным - относительные пути, такие как ./style.css , не поддерживаются. Путь может содержать строку запроса.

Чтобы выдвинуть несколько объектов, вы можете предоставить несколько заголовков Link или, что еще лучше, включить все объекты в список через запятую:

Link: </style.css>; as=style; rel=preload, </favicon.ico>; as=image; rel=preload

Если вы не хотите, чтобы NGINX пушил предварительно загруженный ресурс, добавьте параметр nopush в заголовок:

# Resource is not pushed
Link: </nginx.png>; as=image; rel=preload; nopush

Когда http2_push_preload включен, вы также можете инициировать предварительную загрузку сервера, установив заголовок ответа в вашей конфигурации NGINX:

add_header Link "</style.css>; as=style; rel=preload";

Выборочная передача ресурсов клиентам

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

Одним из возможных подходов является предоставление ресурсов клиентам только при первом посещении сайта. Например, вы можете проверить наличие cookie-файла сеанса и условно установить заголовок Link , чтобы ресурсы загружались предварительно, только если cookie-файл сеанса отсутствует.

Предполагая, что клиенты ведут себя хорошо и включают cookie в последующие запросы, в следующей конфигурации NGINX передает ресурсы клиентам только один раз за сеанс браузера:

server {
    listen 443 ssl http2 default_server;

    ssl_certificate ssl/certificate.pem;
    ssl_certificate_key ssl/key.pem;

    root /var/www/html;
    http2_push_preload on;

    location = /demo.html {
        add_header Set-Cookie "session=1";
        add_header Link $resources;
    }
}

map $http_cookie $resources {
    "~*session=1" "";
    default "</style.css>; as=style; rel=preload, </image1.jpg>; as=image; rel=preload, </image2.jpg>; as=image; rel=preload";
}

Измерение эффекта HTTP/2 Server Push

Чтобы измерить влияние проталкивания сервера, мы создали простую тестовую страницу /demo.html , которая ссылается на отдельную таблицу стилей /style.css . Таблица стилей далее ссылается на два изображения. Мы протестировали время загрузки страницы, используя три разные конфигурации:

  • Sequential GET (без оптимизации) - браузер загружал ресурсы, когда обнаружил, что они необходимы
  • Подсказки предварительной загрузки - Подсказки предварительной загрузки (заголовки Link ) были включены в первый ответ, чтобы сообщить браузеру о загрузке зависимостей.
  • Сервер Push (только HTTP/2) - Зависимости были преимущественно переданы в браузер
Влияние толчка сервера HTTP / 2 на количество циклов (RTT)
Три конфигурации были протестированы, чтобы измерить влияние HTTP/2 с использованием сервера

Мы провели несколько тестовых прогонов для каждой конфигурации, используя HTTP, HTTPS или HTTP/2. Первые две конфигурации применяются ко всем трем протоколам, а сервер проталкивает только HTTP/2.

Поведение было измерено с использованием инструментов разработчика Chrome. Наиболее распространенное поведение каждой конфигурации было оценено и усреднено, а времена были коррелированы с RTT канала (как измерено с помощью ping ), чтобы проиллюстрировать механический эффект каждого метода.

Результаты испытаний, показывающие много поездок туда и обратно были сделаны с каждой конфигурацией

Некоторые Основные Наблюдения

  • DOM загружен - это время для инициации нового соединения и получения страницы demo.htmlТаблица стилей - это время для получения ресурса CSS.
  • Установление соединения по HTTP занимает 1 RTT; для HTTPS и HTTP/2 требуется 2 RTT.
  • Полезная нагрузка для ресурсов HTML и CSS меньше, чем максимальный размер единицы передачи (MTU), поэтому операция GET завершается приблизительно за 1 RTT.

Интерпретация результатов: подсказки предварительной загрузки

  • Подсказки предварительной загрузки имеют минимальный эффект для ресурса CSS, поскольку на него непосредственно ссылаются в ресурсе HTML, а ресурс HTML доставляется быстро. Браузер инициирует запрос CSS, как только HTML-страница доставляется.
  • Подсказки предварительной загрузки позволяют быстро начать загрузку ресурсов, объявленных в ресурсе CSS (здесь два изображения). Загрузка может начаться на 1 RTT быстрее, если используются подсказки предварительной загрузки.
  • Чистая экономия от подсказок предварительной загрузки может составлять 1 RTT или более. При параллельной загрузке ресурсов браузер должен открыть одно или несколько дополнительных подключений. Производительность зависит от того, планируются ли медленные запросы (более крупные ответы) первыми или задерживаются при открытии новых соединений. Этот непредсказуемый порядок запросов учитывает ускорение 1-RTT для HTTP и HTTP/2 и ускорение 2-RTT для HTTPS.

Интерпретация результатов: Server Push

  • Нажим на сервер улучшил время предварительной загрузки на 1 RTT. Push «ответы» были инициированы одновременно с ответом на первый запрос, тогда как ответы с подсказками предварительной загрузки вызвали 1 задержку RTT - 0,5 RTT для ответа на первый запрос плюс 0,5 RTT для запроса GET с предварительной GET.

Тестовые заметки

  • Было несколько тестовых прогонов для каждой конфигурации. Каждый запуск начинался с пустого кеша браузера и без установленных соединений keepalive с сервером NGINX. Директивы NGINX keepalive_timeout и http2_idle_timeout использовались для быстрого закрытия соединений keepalive.
  • В настоящее время не представляется возможным отправить ресурсы шрифтов в Chrome, возможно, из-за известной сложности . Chrome явно запрашивает ресурс шрифта, даже если он уже был передан.
  • Перед каждым тестом были предприняты все усилия, чтобы явно очистить кеши браузера, и весь контент обслуживался с истекшими заголовками управления кэшем.
  • Chrome кеширует предварительно загруженные ресурсы. Эти кэшированные ресурсы не всегда игнорируются при отключении кэширования и не всегда очищаются с помощью явной операции «очистить кэш браузера». (В Chrome один из способов отключить кэширование - установить флажок «Disable cache» на вкладке «Netwok» инструментов разработчика». Чтобы очистить кэш браузера, можно щелкнуть правой кнопкой мыши кнопку обновления браузера с открытыми инструментами разработчика и выбрать « Очистить кэш» и «Жесткая перезагрузка») ,
  • Некоторые попытки предварительной загрузки содержимого приводили к тому, что Chrome безуспешно повторно проверял кэшированные копии, а затем загружал ресурс в обычном режиме. Эти попытки не учитывались при измерениях.
  • Chrome добавляет ненужную задержку 2-RTT ко всем новым соединениям SSL, которые используют ранее принятые самозаверяющие сертификаты. Тест проводился с использованием подписанных CA сертификатов Let's Encrypt, чтобы избежать этой задержки 2-RTT.
  • Задержки DNS были устранены путем редактирования локального файла /etc/hosts .
  • Эти простые тесты не пытались измерить эффект push сервера, когда у клиента уже есть кэшированная копия ресурса. В тестах все кэши очищались перед каждым тестом, и большинство нажатий были слишком быстрыми для отмены.

Заключение

Этот тест был преднамеренно простым, чтобы подчеркнуть механику подсказок предварительной загрузки и подталкивания сервера. Push-сервер обеспечивает улучшение 1-RTT по сравнению с подсказками предварительной загрузки в простых ситуациях и большее улучшение по сравнению с неоптимизированными последовательными запросами GET и обнаружением зависимых ресурсов.

Более реалистичные варианты использования имеют гораздо больше переменных: несколько зависимых ресурсов, несколько источников, даже возможность потери пропускной способности за счет использования ресурсов, которые уже кэшированы или не нужны немедленно. Несоответствия браузера также влияют на производительность. Ваш пробег, безусловно, будет отличаться от этого простого теста.

Например, команда Chrome опубликовала некоторые подробные рекомендации о том, когда следует развертывать push-запросы сервера, и провела измерения на более сложных сайтах, чтобы сравнить результаты без оптимизации, подсказок предварительной загрузки и пересылки по серверу HTTP/2. Их практический отчет по HTTP/2 Push- отчету стоит прочитать всем, кто рассматривает возможность развертывания HTTP/2-сервера push в рабочей среде.

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

Приложение: Как работает HTTP/2 Push?

Приведенная ниже информация частично основана на очень подробном исследовании Push HTTP/2 Джейка Арчибальда, которое сложнее, чем в блоге.

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

Когда клиент устанавливает соединение HTTP/2, сервер может выбрать инициирование одного или нескольких ответов сервера через соединение. Эти Push отправляют ресурсы, которые клиент явно не запрашивал.

Клиент может либо отклонить push (отправив RST_STREAM), либо принять его. Клиент сохраняет загруженный контент в локальном «push-кэше», связанном с HTTP/2-соединением.

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

Любой отправленный ресурс остается в push-кэше для каждого подключения до тех пор, пока (а) он не будет использован или (б) соединение HTTP/2 не будет закрыто:

  1. Если ресурс используется, клиент берет копию, и запись в кеш-памяти удаляется. Если ресурс кэшируется, клиент может затем кэшировать свою копию в своем кэше HTTP-страницы.
  2. Если соединение HTTP/2 по какой-либо причине закрыто, его локальный push-кэш удаляется.

Это имеет несколько последствий:

  • Содержимое в кэше страниц HTTP в браузере используется вместо содержимого в кэше push-уведомлений, даже если передаваемый контент является более свежим.
  • HTTP/2-соединения могут быть общими для разных загрузок страниц. Ресурс, который выдвигается в результате загрузки одной страницы, может использоваться при запросе другой загрузки страницы.
  • Запросы с учетными данными используют разные соединения HTTP/2 из запросов без учетных данных; например, ресурс, который отправляется с запросом кросс-источника (с учетными данными), может быть не найден, если браузер делает запрос к ресурсу без учетных данных.

Вы можете просмотреть гораздо более подробный список проблем в HTTP/2, выдвинутых Джейком Арчибальдом, сложнее, чем в блоге.

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

Официальный сайт