
Все больше и больше компаний начинают использовать 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'а.