Все больше и больше компаний начинают использовать HTTP/2 для повышения производительности своих сайтов. Настроить HTTP/2 довольно просто, но что делать, если в вашей инфраструктуре есть Varnish. Т.к. Varnish 4.* не поддерживает SSL, то нам прийдется найти способ заставить все необходимые компоненты работать друг с другом.
HTTP/2
Как вы знаете, Web постоянно движется вперед и мы наконец-то имеем новую версию HTTP протокола. Ее основными достоинствами являются:
— потоки и мультиплексирование (streams and multiplexing): одно HTTP/2 соединение может содержать множество конкурентных открытых потоков. Мультиплексирование запросов достигается за счет наличия у каждого HTTP запроса/ответа ассоциированного с ним, собственного потока. Потоки не зависят друг от друга, поэтому ожидание одного ответа не влияет на работу других потоков.
— сжатие HTTP заголовков: в HTTP/1.1, заголовки не сжимаются и излишне расходуют пропускную способность, а также увеличивают время передачи по сети. В HTTP/2 был представлен новый механизм сжатия — HPACK. Он устраняет избыточные заголовки, а также понижает степень уязвимости к известным атакам.
— заблаговременная отправка данных с сервера (server pushes): HTTP/2 позволяет серверу преждевременно отправить клиенту ответы, ассоциированные с его предыдущими запросами.
Множество современных браузеров уже поддерживают HTTP/2, поэтому с помощью нескольких простых действий вы получите в них желаемые результаты.
Вы также можете более детально ознакомиться с нововведениями обратившись к официальной спецификации:
— Hypertext Transfer Protocol Version 2 (HTTP/2) — RFC 7540
— HPACK: Header Compression for HTTP/2 — RFC 7541
Зачем нужен HTTP/2?
Объяснения выше хороши, однако некоторые люди любят сами увидеть или почувствовать результат, прежде чем начать что-то делать. Лучшее демо, которое я нашел и которое способно мотивировать других, создано компанией Akamai. В их демо они сравнивают загрузку двух одинаковый изображений, состоящих из множества маленьких сегментов, через HTTP/1.1 и HTTP/2. Если ваш браузер поддерживает HTTP/2, то я рекомендую перейти и посмотреть их HTTP/2 демо. Более того, браузеры требуют SSL для работы HTTP/2, а это сделает ваш сайт более безопасным.
Классическая схема с Varnish
Обычно Varnish ставят между клиентами и веб сервером. Схема выглядит следующим образом:
Здесь у нас есть клиент, который запрашивает страницу. Его запрос идет к Varnish’у, который слушает 80 порт. Далее Varnish проверяет есть ли у него в кеше объект для ответа клиенту:
— при наличии, он возращает ответ клиенту, при этом не обращаясь к веб серверу вообще;
— при отсутствии такого объекта, Varnish передает запрос веб серверу, получает от него ответ и только потом возвращает клиенту (ответ от веб сервера также может быть закеширован).
Проблема в том, что Varnish 4.* не поддерживает SSL, который требуют браузеры для работы с HTTP/2, поэтому мы не можем просто сказать Varnish’у слушать 443 порт.
Решение с Nginx
Одним из возможных решений является добавление Nginx перед Varnish’ем. Он будет отвечать за работу HTTP/2, поддерживать SSL и перенаправлять такие запросы через HTTP/1.1 Varnish’у. Наша новая схема теперь выглядит следующим образом:
Установка Nginx
Минимальная версия Nginx должна быть не менее 1.9.5
(только начиная с данной версии в Nginx доступен необходимый нам модуль — ngx_http_v2_module). Я использую Mac OSX, поэтому напишу об установке с помощью brew:
- brew tap homebrew/nginx
Нам потребуется два модуля, один для HTTP/2 и один для выявления реальных IP после проксирования запросов. Названия необходимых нам опций можно посмотреть с помощью,:
- brew options nginx—full
Для установки Nginx выполним:
- brew install nginx—full —with—http2 —with—realip
Также можно добавить Nginx в автозагрузку:
- brew services start homebrew/nginx/nginx—full
SSL сертификат
Дополнительно, нам понадобится SSL сертификат. Существует множество способов его получения, но сейчас мы остановимся на генерации с помощью openssl
:
- openssl req —newkey rsa:2048 —sha256 —keyout <ПУТЬ К ВЫХОДНОМУ *.key ФАЙЛУ> —nodes —x509 —days 365 —out <ПУТЬ К ВЫХОДНОМУ *.crt ФАЙЛУ>
Обратите внимание, что при генерировании сертификата необходимо будет указать ваш домен на шаге Common Name
. При использовании такого сертификата браузер сообщит, что сертификат ненадежный, однако для наших демо целей это вполне нормально.
Настройка Nginx (HTTP/2, SSL)
Теперь у нас есть все, чтобы настроить Nginx:
- server {
- # 443 — порт по умолчанию дляSSL
- listen 443 ssl http2;
- server_name <ВАШ ДОМЕН>;
- # Указываем наши SSL файлы
- ssl_certificate <ПУТЬ К *.crt ФАЙЛУ>;
- ssl_certificate_key <ПУТЬ К *.key ФАЙЛУ>;
- location / {
- # Устанавливаем рекомендуемую Nginx версию HTTP
- proxy_http_version 1.1;
- proxy_pass http://127.0.0.1:80;
- proxy_set_header X—Real—IP $remote_addr;
- proxy_set_header X—Forwarded—For $proxy_add_x_forwarded_for;
- proxy_set_header X—Forwarded—Proto https;
- proxy_set_header X—Forwarded—Port 443;
- proxy_set_header Host $host;
- }
- }
Настройка Varnish
Минимальный *.vcl файл для Varnish’а:
- vcl 4.0;
- backend local {
- .host = «127.0.0.1»;
- .port = «8080»;
- }
Далее необходимо запустить Varnish на 80
порту:
- varnishd —n vtest —f <ПУТЬ К *.vcl ФАЙЛУ> —s malloc,512M —a 127.0.0.1:80
В качестве альтернативы на данном этапе можно указать флаг -b
(вместо *.vcl файла, по примеру -a).
Настройка веб сервера
В качестве веб сервера я использую Nginx (да, в нашей схеме будет 2 Nginx’а ? ). В настройках Varnish’а мы указали, что бекенд слушает порт 8080, поэтому необходимо настроить Nginx соответствующим образом. Добавим в настройки Nginx еще один сервер:
- server {
- # Указываем порт, на который Varnish перенаправляет запросы (*.vcl файл).
- listen 8080;
- server_name <ВАШ ДОМЕН>;
- # Указываем доверенный адрес, с которого мы разрешаем замещение реального IP.
- set_real_ip_from 127.0.0.1;
- real_ip_header X—Forwarded—For;
- real_ip_recursive on;
- #…
- }
Тестирование с помощью Chrome
Чтобы наглядно проверить работоспособность схемы, установите расширение для Chrome — HTTP/2 and SPDY indicator
.
Развитие Varnish
Исходя из одного из недавних интервью с Varnish Software CTO Per Buer, они проводят серьезную работу в направлении HTTP/2:
H/2 сейчас первый в нашем списке. Мы потратили годы работая над различными изменениями в Varnish, чтобы подготовиться к H/2. Два последних релиза Varnish’а были подготовкой к нему.
Я надеюсь, что в новой версии Varnish Cache будет добавлена поддержка HTTP/2 и мы сможем убрать из нашей инфраструктуры такие компоненты, как дополнительный Nginx.
Выводы
Абсолютно неважно, используете ли вы Varnish для кеширования или же модули Nginx, вы определенно должны работать с HTTP/2 уже сегодня, т.к. это дает ощутимые результаты и требует минимум времени для настройки. Более того, в нашем упрощенном примере все ресурсы будут доступны через 443, 80 и 8080 порты. Если вам необходимо ограничить доступ, то прийдется добавить редирект с внешних IP на уровне Varnish’а или Nginx’а.