Реализуем http/2 server push с помощью nghttp2
На этот раз схема будет следующая:
Теперь непосредственно о самой реализации. В данный момент nginx в режиме HTTP/2 не поддерживает технологию server push. Для этих целей я буду использовать nghttp2 — именно его используют в CloudFlare для реализации push’ей для своих клиентов. nghttp2 — это набор инструментов, реализующих HTTP/2 протокол. А именно: standalone-сервер, клиент и обратный прокси-сервер. Нас интересует часть, реализующая прокси-сервер, программа называется nghttpx.
Настройка
Устанавливаем nghttp2:
apt-get install nghttp2
Настраиваем nghttpx. Файл конфигурации /etc/nghttpx/nghttpx.conf приводим к виду
frontend=93.170.104.204,443 #IP и порт нашей веб-морды
backend=127.0.0.1,6081 #IP и порт бэкенд-сервера
private-key-file=/etc/ssl/ssl.webshake.ru.key #Закрытый ключ
certificate-file=/etc/ssl/ssl.webshake.ru.pem #Файл с сертификатом сайта и сертификатами УЦ, аналогично nginx
http2-proxy=no #Иначе server push будет недоступен
workers=1 #Число воркеров
Проверяем что сайт работает. Теперь для того, чтобы «запушить» файл стилей в браузер клиенту достаточно передать на nghttpx с бэкенда заголовок вида:
Link: /path/to/file.css; rel=preload; as=stylesheet
Для JS-файла заголовок будет таким:
Link: /path/to/file.js; rel=preload; as=script
Я добавил 14 таких заголовков, реализовав это на PHP. В файл index.php добавил строки:
; rel=preload; as=stylesheet", false);
header("link: ; rel=preload; as=stylesheet", false);
header("link: ; rel=preload; as=stylesheet", false);
header("link: ; rel=preload; as=stylesheet", false);
header("link: ; rel=preload; as=stylesheet", false);
header("link: ; rel=preload; as=script", false);
header("link: ; rel=preload; as=script", false);
header("link: ; rel=preload; as=script", false);
header("link: ; rel=preload; as=script", false);
header("link: ; rel=preload; as=script", false);
header("link: ; rel=preload; as=script", false);
header("link: ; rel=preload; as=script", false);
header("link: ; rel=preload; as=script", false);
header("link: ; rel=preload; as=script", false);
и перезапустил Varnish для сброса всего кэша.
Результат
После этого в браузере загрузил главную страницу своего сайта и увидел пушнутые файлы:
А вот так выглядит загрузка с отключенными пушами:
Файл, который был отправлен с помощью server push имеет соответствующий заголовок.
Вот в виде сравнения скорости рендеринга главной страницы при push’е файлов со стилями и JS и без push’ей:
Замеры проводились инструментом WebPagetest/, о котором я узнал от своего коллеги. Проект open-source, доступна куча метрик, настроек и тестовых серверов. Всем советую!
Также в процессе работы я накодил мини-сервис, позволяющий быстро проверить список пушаемых файлов, введя url сайта. Может быть кому пригодится — webshake.ru/services? http2push
Вывод
Технология server push’ей позволила сократить загрузку и отрисовку моего сайта с 1.7 до 1.4 секунд, а это аж 17%! Это работает и должно быть использовано.
Напоследок еще немного метрик с WebPagetest.