Содержание статьи
Немного о проекте
Varnish представляет собой кеширующий «обратный» (reverse) прокси‑сервер и акселератор HTTP. Принцип его работы в общем стандартен для такого класса программ. Он получает запрос, обрабатывает его и сразу выдает ответ, если он присутствует в кеше; если нет, то обращается к веб‑серверу за результатом. Ответ помещается в кеш. Varnish написан с нуля для норвежской газеты Verdens Gang. Версия 1.0 появилась в 2006 году, в 2014-м представлен релиз 4.0. Основной код доступен под BSD-подобной лицензии, но есть и коммерческие модули.
Проект сразу привлек себе внимание весьма громкими заявлениями автора, одного из разработчиков FreeBSD Пола‑Хеннинга Кампа (Poul-Henning Kamp) о том, что все (с намеком на Squid) сделано неправильно. И действительно, Varnish выделяет современный дизайн, эффективно использующий возможности современных многопроцессорных систем (Sqiud научился работать с SMP чуть позже с версии 3.2). Многопоточность реализована с помощью стандартных потоков POSIX, их количество регулируется. Это одна из причин, почему Varnish не очень хорошо работает в Windows. Каждый запрос обрабатывается в отдельном потоке. Причем с версии 4.0 за получение запроса от пользователя и передачу запроса серверу отвечают разные потоки, что еще более повысило производительность. Varnish поддерживает технологию ESI (Edge Side Includes), позволяющую разбивать веб‑страницу на части и запрашивать их отдельно. Кеш может хранить любую информацию. В итоге Varnish отлично подходит для кеширования динамического контента.
Для хранения данных (кеша, журналов операций) используется виртуальная память. Управлением того, что выгружается на диск, занимается ОС. Здесь авторы Varnish справедливо считают, что разработчики ОС свое дело знают, а дублирование только ухудшает производительность.
В отличие от Squid, который изначально больше ориентировался на кеширование клиентских запросов, Varnish был разработан и оптимизирован именно в качестве ускорителя HTTP и ничего другого больше не умеет. Мы не найдем здесь поддержку остальных протоколов (FTP, SMTP и прочие), не увидим возможности прямого прокси — кеширования веб‑страниц для экономии внешнего трафика (Varnish «привязывается» к бэкендам). Естественно, отличаются и возможности по конфигурированию.
Язык конфигурации Varnish Configuration Language (VCL) — динамический, скрипт сам по себе по сути является отдельным плагином. Код транслируется в С (можно сразу писать встраиваемый код на С), после чего инструкции компилируются в библиотеку и подгружаются в память. Можно вносить изменения в конфигурацию на лету. Инструкции в VCL позволяют кешировать только определенные запросы, снижая нагрузку при генерации динамических объектов, блокировать доступ к определенным каталогам и скриптам, подменять заголовки и многое другое. Есть и механизм проверки работоспособности бэкендов (замер времени ответа, счетчик неудачных проверок и так далее), возможность перезаписи и перенаправления (rewrite) запросов. Вообще, такой подход позволяет производить с HTTP-трафиком практически любые манипуляции, которые можно ограничить только собственным воображением. Поддерживается балансировка нагрузки (round robin, random и DNS, Client IP). Возможности расширяются при помощи модулей, называемых VMOD (Varnish MODules). Проект предоставляет необходимую документацию, позволяющую написать такой модуль самостоятельно. Часть модулей уже включены в стандартную поставку, некоторые доступны в виде концепта или находятся в разработке.
Сегодня Varnish используют такие веб‑сервисы, как Facebook, Twitter, Vimeo и Tumblr.
Установка и базовая настройка Varnish
Официально рекомендуется установка Varnish на современных версиях x64-битных Linux, FreeBSD или Solaris. Пакеты можно найти в дополнительных репозиториях (вроде EPEL или Ubuntu Universe) большинства дистрибутивов Linux и портах *BSD-систем. Сам проект предоставляет репозитории и подробные инструкции для Red Hat, Debian, Ubuntu и FreeBSD. В большинстве случаев следует использовать именно репозиторий разработчика, так как в нем находится более свежая версия продукта. Возможна работа и в Windows (через Cygwin), но оптимизация под *nix-системы не гарантирует максимальной производительности результата. На сайте доступны две версии Varnish — 3.x и 4.x, обе являются стабильными, но поддержка линейки 3.x будет прекращена в первой половине 2015 года. Кстати, код достаточно хорошо написан, поэтому исправлений вносится мало (например, 3-я ветка, появившаяся в июне 2011-го, содержала всего шесть версий), можно не бояться использовать свежие релизы. Стандартно Varnish ставится перед веб‑сервером и кеширует запросы. В нагруженных системах иногда используют более сложный вариант, когда вначале запрос принимает легкий веб‑сервер (nginx, lighttpd), который умеет быстро отдавать определенные страницы. При необходимости этот сервер через Varnish обращается к основному HTTP-серверу, генерирующему контент. Varnish при наличии информации в кеше отдает ее оттуда.
Для примера установим Varnish в Ubuntu 14.04 LTS в качестве фронтенда Apache. В других дистрибутивах отличия только в расположении конфигурационных файлов и особенностях пакетных систем.
$ sudo apt-get install apt-transport-https curl
$ sudo curl https://repo.varnish-cache.org/ubuntu/GPG-key.txt | apt-key add -
$ sudo echo "deb https://repo.varnish-cache.org/ubuntu/ trusty varnish-4.0" >> /etc/apt/sources.list.d/varnish-cache.list
$ sudo apt-get update
$ sudo apt-get install varnish
Вот, собственно, и все. После установки Varnish стартует и что‑то там кеширует. Займемся конфигурированием. Установки параметров запуска демона производятся в файле /etc/default/varnish. Первоначально он сконфигурирован с некоторыми параметрами. Если открыть файл, то увидим внутри три готовые настройки: minimal, c VCL и advanced.
По умолчанию активирован второй режим. При этом сервер принимает подключения на порт 6081, для администрирования используется localhost:6082, а бэкенд определяется в VCL. Для кеширования выделяется 256 Мб памяти. Настроим так, чтобы Varnish слушал 80-й порт, кешируя запросы HTTP-сервера, расположенного на этой же машине. Комментируем настройки второго варианта и в качестве шаблона будем использовать advanced, как более наглядный.
$ sudo nano /etc/default/varnish
# Запускать демон varnishd при загрузке системы.START=yes# Максимальное количество открытых файлов (для ulimit -n)NFILES=131072
# Максимальное количество залоченной памяти (for ulimit -l) для блокировки разделяемой памяти лога# При необходимости следует увеличить размерMEMLOCK=86000
# По умолчанию экземпляр сервера получает имя текущего узла. При запуске нескольких экземпляров его можно переопределить при помощи -n или# INSTANCE=$(uname -n)# По умолчанию слушаются все интерфейсы, но можем указать IP# VARNISH_LISTEN_ADDRESS=# Порт, на котором принимаются подключенияVARNISH_LISTEN_PORT=80
# Админ-интерфейс IP и портVARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082
# VCL-файлVARNISH_VCL_CONF=/etc/varnish/default.vcl
DAEMON_OPTS="\ -a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \ -f ${VARNISH_VCL_CONF} \ -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:$ {VARNISH_ADMIN_LISTEN_PORT} \
Это основные установки. С остальными можно познакомиться в файле или в документации проекта. Перестраиваем Apache, чтобы он слушал 8080-й порт. В зависимости от текущих установок это можно сделать в разных файлах, в общем идея выглядит так:
$ sudo nano /etc/apache2/ports.conf
NameVirtualHost *:8080
Listen 8080
Теперь осталось указать Varnish, где находится HTTP-сервер. В /etc/default/varnish это можно сделать при помощи ключа -b (-b localhost:8080), но удобнее для этого использовать VCL-файл, который указан в переменной VARNISH_VCL_CONF (в сырцах есть пример example.vcl). Открываем и смотрим, чтобы внутри была инструкция:
$ sudo nano /etc/varnish/default.vcl
backend apache { .host = "127.0.0.1"; .port = "8080";}
Минимальные установки готовы. Перезапускаем Varnish:
$ sudo service varnish start
Проверяем при помощи netstat, слушается ли порт и доступен ли веб‑сервер.
Продвинутые настройки
Это самый простой пример, и, как видим, заставить Varnish кешировать запросы очень легко, но он пока не «разбирается» и не вмешивается в трафик. Познакомившись с VCL, можно расширить базовые возможности. Параметров, которые можно настроить, очень много и, чтобы их описать, потребуется книга. VCL — это язык программирования, в котором найдем все, что положено: переменные, функции, комментарии и прочее. Вариантов использования много, и с ходу их освоить не получится. В качестве отправной точки можно рекомендовать документацию проекта, в частности Varnish Book. Также в Сети уже есть достаточно шаблонов под разные ситуации, подготовленных самими пользователями. Они будут хорошим подспорьем при изучении возможностей VCL.
Varnish способен работать с несколькими HTTP-серверами (бэкендами). Каждый определяется аналогично примеру выше:
backend server1 { .host = "10.0.0.11";}backend server2 { .host = "10.0.0.12";}
После чего можно строить правила, указывая серверы по имени. Если бэкенды равнозначны и используются только для распределения нагрузки, то достаточно сообщить об этом Varnish с помощью директивы director:
director balanced_servers round-robin { { .backend = server1; } { .backend = server2; } }
Можно также использовать случайный выбор — для этого вместо round-robin прописываем random. Возможна реализация и более сложных алгоритмов. Но для этого нужно познакомиться с возможностями VCL-файлов. В default.vcl мы увидим несколько именованных блоков (функций). По умолчанию параметры внутри отсутствуют, вот именно с их помощью и производится тонкая настройка кеширования. Кое‑что можно установить, не вникая в работу приложений на веб‑сервере, в более сложных случаях потребуется глубокий анализ выдаваемых страниц (проект предоставляет несколько утилит, о которых дальше).
Разберем некоторые из них. Порядок вызова функций наглядно показан в разделе VCL Basics, отдельные вопросы конфигурирования есть в документации. Списки ACL позволяют управлять доступом к определенным URL или вручную распределять или обрабатывать запросы некоторых клиентов. Создадим правило, которое включает все локальные узлы.
acl local { "localhost"; "192.168.1.0"/24; ! "192.168.1.10"; }
Как видим, разрешается инвертирование при помощи !, то есть 192.168.1.10 не попадает под правило. Теперь к этому списку можем обратиться при помощи конструкции (client.ip ~ local).
Функция vcl_recv вызывается при получении запроса и перед проверкой данных в кеше. Именно здесь можно модифицировать запрос, удалить cookie, произвести нормализацию, выбрать бэкенд в зависимости от запроса. По умолчанию Varnish не кеширует запросы с установленными cookie. Для статических страниц лучше активировать такую возможность, для этого просто вырезаем cookie. Также для примера запретим доступ к файлам cron.php и install.php для всех узлов, кроме локальных, и скажем Varnish, чтобы он перенаправлял все запросы к update.php сразу на бэкенд.
sub vcl_recv { set req.backend = apache
if (req.url ~ "\.(css|js|png|gif|jp(e)?g)") { unset req.http.cookie; } return (lookup); if (req.url ~ "^/(cron|install)\.php$" && !client.ip ~ local) { error 404 "Page not found."; } if (req.url ~ "^/update\.php$" return (pass); } }
Это, конечно, не все, что можно сделать. Используя req.http.User-Agent, можем распределять бэкенды в зависимости от браузера/устройства клиента. Подробнее. Функция return в случае с vcl_recv может принимать аргументы: lookup — указывает на необходимость поиска в кеше, pass — сразу отправляет запрос на бэкенд. Последнее, как видим, позволяет избежать кеширования определенных типов файлов, например медиа или постоянно обновляющегося контента.
Некоторые функции вызывают пустыми, просто чтобы пропустить определенную проверку, указав нужный код возврата. Кроме указанных выше, возможны варианты: deliver, fetch, hash, pipe, error, restart, retry. Функция vcl_hash позволяет определить уникальность запроса, который будет кешироваться. По умолчанию хеш формируется на основании URL и IP/имени сервера. В большинстве случаев этого достаточно, но в некоторых ситуациях этого не хватает и, возможно, потребуется изменение правил. Например, для определения уникальности используют Сookie.
Функция vcl_error позволяет генерировать контент, не обращаясь к веб‑серверу. Используется для выдачи сообщений об ошибках и редиректа. Далее в зависимости от ситуации запрос обрабатывается vcl_fetch, vcl_pass и vcl_miss. В 4.0 они заменены на более удобные функции vcl_backend_fetch и vcl_backend_response, которые вызываются перед передачей запроса серверу и после получения ответа соответственно.
В следующем примере мы убираем выставление cookie для файлов изображений, а также задаем время жизни кешированного содержимого для этих файлов в один час.
sub vcl_backend_response { if (bereq.url ~ "\.(png|gif|jpg)$") { unset beresp.http.set-cookie; set beresp.ttl = 1h; }}
И перед отправкой полученных от бэкенда данных вызывается функция vcl_deliver. В простейшем случае она пустует, то есть ответ передается без изменений. Но здесь можно при желании модифицировать заголовки. Для примера просто удалим все упоминания о Varnish:
sub vcl_deliver { remove resp.http.X-Varnish; remove resp.http.X-Powered-By;}
Это, конечно, далеко не все возможности, но нужно идти дальше.
Управление Varnish
Работой Varnish можно управлять и отслеживать результат. Для этого в поставке идет несколько утилит, начинающихся с varnish*. Все они описаны в разделе «Appendix A: Varnish Programs» Varnish Book. Основной утилитой является varnishadm. Именно с ее помощью производится администрирование, просмотр статуса и ошибок, загрузка модулей на лету. Принцип работы очень прост. Вызываем:
$ sudo varnishadm
После чего появится приглашение Varnish CLI. Чтобы получить список команд, следует ввести help.
Команд немного (23), значение большинства понятно из названия. Подробности по каждой можно получить, введя «help команда». Например, группа команд vcl.* позволяет просматривать модули и управлять их загрузкой‑выгрузкой. Смотрим список модулей:
varnish> vcl.list
Команды param.show и param.set позволяют просматривать и изменять параметры сервиса, panic.show и panic.clear — отображать и очищать ошибки, ban и ban.list — указывать страницы, не подлежащие кешированию. Две команды varnishtop и varnishhist очень помогают при первоначальной настройке, так как позволяют просмотреть список наиболее часто встречающихся параметров (URL, идентификаторы, статус и так далее). Первая утилита выводит их в виде top, вторая как гистограмму. При запросе можно использовать регулярные выражения, поэтому потеряться в большом количестве страниц невозможно. Например, просмотрим список наиболее запрашиваемых URL и заголовки:
$ varnishtop -i RxUrl
$ varnishtop -i RxHeader
Еще три очень полезные утилиты, позволяющие просмотреть статистику (varnishstat) и информацию в журналах (varnishlog и varnishncsa). Скрипт varnishtest дает возможность проверить работу кеша Varnish. Для тех, кто не хочет разбираться с командной строкой, разработчики предлагают веб‑интерфейс Varnish Administration Console — очень удобный инструмент, предлагающий произвести все описанные операции и получать статистику в наглядном виде.
Правда, есть минус — доступен он только в коммерческой версии Varnish Plus. Бесплатное ПО пока небогато вариантами. Плагины, поддерживающие Varnish, есть в системах мониторинга Collectd, Nagios, Cacti и других. Список известных проектов можно найти на сайте.
Вывод
Varnish — это очень гибкая программа, позволяющая управлять кешированием трафика с веб‑ресурсов. Большие возможности подразумевают большое количество настроек. Поэтому некоторое время придется затратить на их изучение и подгонку под конкретные условия. Но результат того стоит.