Увеличение скорости сайта Drupal 7 с помощью Varnish 4 в Ubuntu 14.04 и Debian 7

Drupal – одна из популярнейших систем управления контентом с открытым исходным кодом.

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

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

Существует множество решений проблем производительности, большинство из которых сводится к масштабированию.

Varnish помогает выполнить масштабирование на уровне программного обеспечения, добавляя дополнительное ПО для устранения узких мест.

Этот мануал выполнен на Ubuntu 14.04, но с незначительными изменениями путей он будет работать и на Debian 7. Он может подойти и другим дистрибутивам (с незначительными изменениями в командах).

Что такое Varnish?

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

Varnish может использоваться для обслуживания статического контента (такого как изображения, сценарии или таблицы стилей), потому что Varnish невероятно быстрый и справляется с трафиком намного лучше, чем Apache. Он также может использоваться для кэширования квазистатического контента (который динамически генерируется приложением при помощи БД, его подготовка занимает значительное количество времени).

Например, когда на веб-сайте публикуется статья, она редко обновляется. В этом случае совершенно необязательно задействовать все фрагменты Drupal для вычисления и отображения одной и той же статьи при каждом запросе. Было бы хорошо, если бы Varnish сам знал, что обслужить на этой странице, вообще не обращаясь к Drupal. Это облегчает обработку множества запросов, так как обслуживание кэшированной страницы требует очень небольшой вычислительной мощности.

Varnish может ускорить загрузку практически любого сайта (с поправкой на архитектуру) и помогает справиться с неожиданными скачками трафика. Благодаря этому улучшается пользовательский опыт.

Требования

  • Мануал предполагает, что у вас есть готовый сайт на основе Drupal и LAMP.
  • Сервер Ubuntu 14.04 или Debian 7 (руководства по начальной настройке можно найти здесь и здесь).
  • Стек LAMP (мануал по настройке – по этой ссылке).
  • Drupal (установить платформу вам поможет мануал Установка Drupal+Apache на Ubuntu 14.04).

1: Настройка Apache

По умолчанию Apache для обработки запросов прослушивает порт 80. Varnish должен получать эти запросы первым. Для этого нужно изменить порт веб-сервера.

Настройки порта находятся в файле ports.conf, который в Debian и Ubuntu хранится в каталоге /etc/apache2.

sudo nano /etc/apache2/ports.conf

На экране вы увидите стандартный файл. Обновите директивы NameVirtualHost и Listen, указав в них порт 81.

# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default
# This is also true if you have upgraded from before 2.2.9-3 (i.e. from
# Debian etch). See /usr/share/doc/apache2.2-common/NEWS.Debian.gz and
# README.Debian.gz
NameVirtualHost *:81
Listen 81
<IfModule mod_ssl.c>
# If you add NameVirtualHost *:443 here, you will also have to change
# the VirtualHost statement in /etc/apache2/sites-available/default-ssl
# to <VirtualHost *:443>
# Server Name Indication for SSL named virtual hosts is currently not
# supported by MSIE on Windows XP.
Listen 443
</IfModule>

Сохраните и закройте файл (CTRL+x, y, Enter).

Изменение порта виртуального хоста

По умолчанию каждая свежая установка Apache имеет один виртуальный хост, /etc/apache2/sites-enabled/000-default. Если у вас больше виртуальных хостов, вам нужно будет отредактировать все эти файлы.

Откройте файл виртуального хоста:

sudo nano /etc/apache2/sites-enabled/000-default.conf

Файл начинается со строк:

<VirtualHost *:80>
ServerAdmin webmaster@localhost

Как и в предыдущем файле, здесь нужно заменить 80 на 81:

<VirtualHost *:81>
ServerAdmin webmaster@localhost

Сохраните и закройте файл (CTRL+x, y, Enter).

Перезагрузка конфигурации Apache

После этого нужно перезагрузить веб-сервер, чтобы обновить его настройки.

sudo service apache2 reload

После этого Apache будет принимать трафик по порту 81, а не 80.

Чтобы проверить это, откройте сайт в браузере. Ссылка на стандартный порт (http://example.com) не будет работать. Теперь сайт должен быть доступен по ссылке на новый порт (http://example.com:81).

2: Установка Varnish

Debian и Ubuntu предоставляют пакет Varnish в стандартном репозитории. Но чтобы получить последнюю версию Varnish, рекомендуется использовать предварительно скомпилированные пакеты, предоставляемые разработчиками Varnish.

Для начала установите пакет apt-transport-https, который позволяет системе устанавливать пакеты по безопасному соединению.

sudo apt-get install apt-transport-https

Если пакет был установлен ранее, команда сообщит об этом.

Чтобы проверить подлинность установленных пакетов, необходимо установить открытый ключ сервера пакетов Varnish. Сначала переключитесь на root:

sudo su

Добавьте ключ:

curl https://repo.varnish-cache.org/ubuntu/GPG-key.txt | apt-key add -
# в Debian:
echo "deb https://repo.varnish-cache.org/debian/ wheezy varnish-4.0" >> /etc/apt/sources.list.d/varnish-cache.list
# в Ubuntu:
echo "deb https://repo.varnish-cache.org/ubuntu/ trusty varnish-4.0" >> /etc/apt/sources.list.d/varnish-cache.list

После этого можно вернуться к пользователю с доступом к sudo.

Обновите систему:

sudo apt-get update

Установите Varnish:

sudo apt-get install varnish

3: Настройка порта Varnish

По умолчанию Varnish прослушивает порт 6081. Нужно настроить Varnish для прослушивания порта 80, чтобы он мог обрабатывать входящие запросы пользователей вместо Apache.

Откройте конфигурационный файл Varnish:

sudo nano /etc/default/varnish

Найдите раскомментированный блок:

. . .
## Alternative 2, Configuration with VCL
#
# Listen on port 6081, administration on localhost:6082, and forward to
# one content server selected by the vcl file, based on the request.
# Use a 256MB memory based cache.
#
DAEMON_OPTS="-a :6081 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,256m"
. . .

Обновите номер порта в строке DAEMON_OPTS=»-a:

. . .
DAEMON_OPTS="-a :80 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,256m"
. . .

Сохраните и закройте файл.

Перезапустите Varnish, чтобы обновить настройки.

sudo service varnish restart
[ ok ] Stopping HTTP accelerator: varnishd.
[ ok ] Starting HTTP accelerator: varnishd.

Теперь проверьте веб-сайт в браузере. Вместо сайта Drupal, который ранее был доступен по этой ссылке, вы должны получить сообщение об ошибке:

Error 503 Backend fetch failed
Backend fetch failed
Guru Meditation:
XID: 131081
Varnish cache server

Это означает, что Varnish настроен для приема входящих соединений, но пока недоступен для обслуживания сайта Drupal.

4: Как работает Varnish

Много полезной информации о Varnish можно найти в Varnish Book.

Язык VCL

Конфигурации Varnish пишутся на языке VCL (Varnish Configuration Language). Это простой язык программирования, который Varnish компилирует в код C.

Конфигурация состоит из методов, которые выполняются в разные моменты обработки входящих веб-запросов вместе с остальной конфигурацией.

Некоторые инструкции Varnish выполняет, когда он получает запрос от браузера, но до того, как запрос будет обработан; это позволяет Varnish определить, следует ли пересылать запрос приложению или можно обслужить кэшированный контент. В этих инструкциях можно управлять входящими запросами, изменять их содержимое или принимать решения на основе запроса (URL-адрес, имя файла, заголовки или куки-файлы).

Другие инструкции выполняются тогда, когда Varnish запрашивает контент из самого приложения (в данном случае – с веб-сайта Drupal). Эти инструкции можно использовать для управления содержимым, полученным от приложения.

Остальные инструкции выполняются, когда Varnish обслуживает кэшированный контент, не извлекая его из приложения.

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

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

Что кэширует Varnish?

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

При типичной установке Drupal это может привести к двум проблемам.

Если у Varnish будет недостаточно кэшированных страниц, то Varnish будет почти бесполезен. Он не ускоряет работу сайта, так как большинство страниц каждый раз извлекается непосредственно из приложения Drupal. Он не создает дополнительных ошибок, но и не решает проблемы с производительностью.

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

Рассмотрим общие факторы, которые помогут решить, какой контент кэшировать.

Varnish кэширует весь контент

По умолчанию Varnish кэширует все. Кэширование в Varnish является эксклюзивным, а не инклюзивным. Это значит, что Varnish будет кэшировать все, если не сказано другого.

Метод request

Метод request – это базовое определение запроса. По умолчанию Varnish кэширует только GET и HEAD, и не кэширует POST, PUT и DELETE. Благодаря этому запросы, которые предназначены для внесения изменений в данные, не попадают в кэш.

Авторизация

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

Заголовки кэширования

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

Куки

Куки-файлы, пожалуй, самая важная и сложная часть кеширования.

По умолчанию, если у приложения есть куки запросов или ответов, страница не будет кэшироваться. Это разумное решение, поскольку, например, зарегистрированные пользователи идентифицируются куки-файлами сеанса. Если страницы с куки будут кэшироваться, все зарегистрированные пользователи получат одинаковый контент, и приложение не сможет различать пользователей. Однако это также является одним из самых серьезных источников проблем, поскольку использование куки-файлов широко распространено. Часто в запросах присутствуют безобидные куки, такие как токены Google Analytics, которые вообще не используются приложением, но также делают контент несовместимым. Решение о том, какие куки нужно исключить из кэша, а какие – игнорировать, нужно продумать очень тщательно, поскольку иначе кеширование будет работать очень плохо, ведь вокруг вас куча куки.

Большинство фрагментов специфичной конфигурации Drupal для Varnish будут удалять ненужные куки и разрешить кэширование, но сохранять необходимые куки, например, для поддержки функциональности страницы администрирования.

5: Настройка Varnish для поддержки Drupal

Теперь у вас есть базовое понимание принципов работы Varnish. Пора настроить этот инструмент для работы с Drupal.

Откройте файл VCL:

sudo nano /etc/varnish/default.vcl

По умолчанию все методы Varnish пусты.

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

Первый блок сообщает Varnish, как связаться с веб-сервером на бэкэнде, (в данном случае это Apache с установкой Drupal). Укажите порт 81, который прослушивает Apache.

. . .
# Default backend definition. Set this to point to your content server.
backend default {
.host = "127.0.0.1";
.port = "81";
}
. . .

Теперь найдите пустой метод vcl_recv:

. . .
sub vcl_recv {
# Happens before we check if we have this in cache already.
#
# Typically you clean up the request here, removing cookies you don't need,
# rewriting the request, etc.
}
. . .

Код в этом методе выполняется до того, как Varnish подключается к сайту Drupal. На этом этапе можно удалить некоторые cookie-файлы из браузера, принудительно кэшировать (или не кэшировать) определенные адреса и принять первое решение по кешированию. Добавьте несколько правил, которые выполнят следующее:

  1. Разрешат Varnish обслуживать устаревший кэш-контент в случае сбоя Drupal. Это сделает сайт частично доступным, даже если Drupal не сможет ответить на запрос.
  2. Отключат кэширование страниц по управлению, исключая из кэша Varnish определенные URL-адреса.
  3. Обеспечат кэширование статических файлов – изображений, сценариев, таблиц стилей.
  4. Удалят все куки-файлы, кроме нескольких, необходимых Drupal для правильной работы (включая функции входа пользователя).

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

. . .
sub vcl_recv {
# Return (pass) instructs Varnish not to cache the request
# when the condition is met.
## ADMIN PAGES ##
# Here we filter out all URLs containing Drupal administrative sections
if (req.url ~ "^/status\.php$" ||
req.url ~ "^/update\.php$" ||
req.url ~ "^/admin$" ||
req.url ~ "^/admin/.*$" ||
req.url ~ "^/user$" ||
req.url ~ "^/user/.*$" ||
req.url ~ "^/flag/.*$" ||
req.url ~ "^.*/ajax/.*$" ||
req.url ~ "^.*/ahah/.*$") {
return (pass);
}
## BACKUP AND MIGRATE MODULE ##
# Backup and Migrate is a very popular Drupal module that needs to be excluded
# It won't work with Varnish
if (req.url ~ "^/admin/content/backup_migrate/export") {
return (pipe);
}
## COOKIES ##
# Remove cookies for stylesheets, scripts, and images used throughout the site.
# Removing cookies will allow Varnish to cache those files.
if (req.url ~ "(?i)\.(css|js|jpg|jpeg|gif|png|ico)(\?.*)?$") {
unset req.http.Cookie;
}
# Remove all cookies that are not necessary for Drupal to work properly.
# Since it would be cumbersome to REMOVE certain cookies, we specify
# which ones are of interest to us, and remove all others. In this particular
# case we leave SESS, SSESS and NO_CACHE cookies used by Drupal's administrative
# interface. Cookies in cookie header are delimited with ";", so when there are
# many cookies, the header looks like "Cookie1=value1; Cookie2=value2; Cookie3..."
# and so on. That allows us to work with ";" to split cookies into individual
# ones.
#
# The method for filtering unnecessary cookies has been adopted from:
# https://fourkitchens.atlassian.net/wiki/display/TECH/Configure+Varnish+3+for+Drupal+7
if (req.http.Cookie) {
# 1. We add ; to the beginning of cookie header
set req.http.Cookie = ";" + req.http.Cookie;
# 2. We remove spaces following each occurence of ";". After this operation
# all cookies are delimited with no spaces.
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
# 3. We replace ";" INTO "; " (adding the space we have previously removed) in cookies
# named SESS..., SSESS... and NO_CACHE. After this operation those cookies will be
# easy to differentiate from the others, because those will be the only one with space
# after ";"
set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=", "; \1=");
# 4. We remove all cookies with no space after ";", so basically we remove all cookies other
# than those above.
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
# 5. We strip leading and trailing whitespace and semicolons.
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
# If there are no cookies after our striping procedure, we remove the header altogether,
# thus allowing Varnish to cache this page
if (req.http.Cookie == "") {
unset req.http.Cookie;
}
# if any of our cookies of interest are still there, we disable caching and pass the request
# straight to Apache and Drupal
else {
return (pass);
}
}
}
. . .

Следующий метод – vcl_backend_response. Этот метод отвечает за обработку ответа от Apache и Drupal перед тем, как поместить его в кэш или удалить его из кэша. Вы можете изменить то, что отправляет Drupal, чтобы вписать это в стратегию кэширования.

Метод по умолчанию выглядит следующим образом:

. . .
sub vcl_backend_response {
# Happens after we have read the response headers from the backend.
#
# Here you clean the response headers, removing silly Set-Cookie headers
# and other mistakes your backend does.
}
. . .

Замените его таким методом:

. . .
sub vcl_backend_response {
# Remove cookies for stylesheets, scripts and images used throughout the site.
# Removing cookies will allow Varnish to cache those files. It is uncommon for
# static files to contain cookies, but it is possible for files generated
# dynamically by Drupal. Those cookies are unnecessary, but could prevent files
# from being cached.
if (bereq.url ~ "(?i)\.(css|js|jpg|jpeg|gif|png|ico)(\?.*)?$") {
unset beresp.http.set-cookie;
}
}
. . .

Этот код удаляет куки статических файлов при помощи уже знакомого метода. Куки для одних и тех же файлов удалены из vcl_backend_response и vcl_recv.

Сохраните и закройте конфигурационный файл.

6: Перезапуск Varnish

Перезапустите Varnish, чтобы обновить настройки:

sudo service varnish restart

Обновление должно произойти без ошибок.

Теперь вы можете просмотреть сайт Drupal в браузере.

Осталось только включить кэширование в Drupal.

7: Настройка кэширования в Drupal

По умолчанию в Drupal отключены механизмы кэширования. Потому Drupal отправляет Varnish заголовки, которые блокируют кэширование. Таким образом, отключенный кэш Drupal автоматически отключает все настройки Varnish, и сайт не будет работать быстрее.

Чтобы включить кэширование Drupal, войдите на сайт Drupal как администратор.

Выберите меню Configuration, а затем Performance.

В разделе Performance найдите и проверьте страницы Cache pages for anonymous users и Cache blocks.

Установите минимальный срок хранения кэша (Minimum cache lifetime) и срок действия кэшированных страниц (Expiration of cached pages), выберите разумные значения, например 30 минут. Это дает значительный прирост производительности и не дает кэшу устареть. Эти значения индивидуальны для каждого сайта и зависят от того, как часто он обновляется. После изменения значений нажмите Save configuration.

8: Проверка конфигурации

Чтобы убедиться, что Varnish кэширует данные сайта, используйте простой инструмент Is Varnish Working?. Введите адрес своего сайта и ждите ответа.

Если в первый раз вы получили сообщение «sort of», повторите проверку.

Читайте также:

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

Tags: , , ,