Ускорьте WordPress с помощью Varnish Cache

WordPress — широко используемая система управления контентом, но страницы часто загружаются медленно, особенно при высоком трафике. К счастью, есть решение этой проблемы – Лак.

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

В этой статье мы покажем вам, как ускорить WordPress с помощью Varnish в системе на базе RedHat. Предположим, что ваш сайт WordPress размещен на NGINX.

Чем Varnish превосходит плагины кеширования WordPress

Важно понимать множество преимуществ Varnish, по сравнению с которыми плагины кеширования WordPress меркнут:

  • Varnish кэширует целые страницы и обслуживает их без использования PHP. Плагины кэширования WordPress используют PHP для доставки кэшированных страниц, что происходит медленно. Вы можете настроить многие плагины кеширования WordPress для обслуживания кешированных страниц через NGINX, но это все равно медленно, поскольку основано на проверке файлов на диске.
  • Varnish по умолчанию использует оперативную память в качестве хранилища кэша. Кэшированная страница доставляется вообще не касаясь диска!
  • Varnish имеет потрясающий язык конфигурации VCL, который позволяет вам быть очень гибкими в правилах настройки кэша.

Шаг 1. Удалите существующий плагин кеширования.

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

Обратите внимание, что это не относится к плагинам кэша объектов. Плагины объектного кэша прекрасно дополнят ваш полностраничный кэш на основе Varnish.

Шаг 2: Установите Varnish

Следующий шаг — установка Varnish на ваш сервер.
В настоящее время мы рекомендуем загрузить Varnish 6.0.x LTS, используя наш репозиторий. Например, в системе CentOS/RHEL 7 вы можете запустить:

sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm yum-utils
sudo yum-config-manager --enable getpagespeed-extras-varnish60
sudo yum -y install varnish

Если вы хотите использовать версию Varnish, поставляемую с вашей операционной системой, используйте следующую команду:

sudo yum install varnish

После установки Varnish вы можете включить его автоматический запуск и немедленный запуск с помощью следующей команды:

sudo systemctl enable --now varnish

По умолчанию Varnish прослушивает порт 6081. Вам не нужно менять его порт. Мы собираемся использовать NGINX в качестве терминатора TLS. Он будет перенаправлять запросы в Varnish, и мы сможем продолжать использовать NGINX для перенаправления HTTP на HTTPS.

Шаг 3. Настройте Varnish

Конфигурация Varnish требует внесения изменений /etc/varnish/default.vcl. Что мы собираемся сделать, так это определить, с каким сервером Varnish должен взаимодействовать, чтобы получать контент, когда Varnish получает запрос. Это наш «основной» серверный блок NGINX.
И мы также настроим, как Varnish будет обрабатывать запросы на очистку кэша.

Вот пример конфигурации Varnish, которого будет достаточно для установки WordPress, в которой нет плагинов, не поддерживающих кэширование (о них читайте ниже):

vcl 4.0;

# Where Varnish should forward requests
backend default {
    .host = "127.0.0.1";
    .port = "8080";
}

# Which IP addresses can send cache purge requests
acl purge {
    "localhost";
    "127.0.0.1";
    "::1";
}
sub vcl_recv {   
    # Remove the proxy header to mitigate the httpoxy vulnerability
    # See https://httpoxy.org/
    unset req.http.proxy;

    # Purge logic
    if(req.method == "PURGE") {
        if(!client.ip ~ purge) {
            return(synth(405,"PURGE not allowed for this IP address"));
        }
        if (req.http.X-Purge-Method == "regex") {
            ban("obj.http.x-url ~ " + req.url + " && obj.http.x-host == " + req.http.host);
            return(synth(200, "Purged"));
        }
        ban("obj.http.x-url == " + req.url + " && obj.http.x-host == " + req.http.host);
        return(synth(200, "Purged"));
    }
}

sub vcl_backend_response {
    # Inject URL & Host header into the object for asynchronous banning purposes
    set beresp.http.x-url = bereq.url;
    set beresp.http.x-host = bereq.http.host;
}

sub vcl_deliver {
    # Cleanup of headers
    unset resp.http.x-url;
    unset resp.http.x-host;    
}

Теперь вы можете перезагрузить конфигурацию Varnish, перезапустив ее:

systemctl restart varnish

Шаг 4. Установите необходимые плагины WordPress.

Varnish кэширует последние версии ваших страниц WordPress, и вам нужно будет установить плагин, который может автоматически аннулировать кэшированные страницы при внесении изменений. Мы рекомендуем использовать плагин Proxy Cache Purge.

Кроме того, WordPress можно включить для лучшей совместимости Varnish с плагином Cacheability. Он будет инструктировать его кэшировать данные дольше с правильным заголовком Cache-Control.

Установите и активируйте плагины с помощью WordPress CLI:

wp plugin install cacheability varnish-http-purge --activate

После установки плагинов вы можете настроить WordPress, указав IP-адрес и порт Varnish:

wp option add vhp_varnish_ip 127.0.0.1:6081

Шаг 5. Настройте NGINX

Следующий шаг — настроить NGINX для работы с Varnish. Мы настроим NGINX как «сэндвич», где первый сервер NGINX будет выступать в роли терминатора TLS, а второй сервер NGINX будет перенаправлять запросы на Varnish.

Для этого нам нужно будет внести некоторые изменения в существующий файл конфигурации NGINX. Для простоты объяснения мы предполагаем, что ваша текущая настройка NGINX состоит из двух server блоков. Один блок выполняет перенаправление HTTP на HTTPS, а другой блок фактически обрабатывает запросы PHP, он же главный блок сервера:

# the redirection server block:
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

# the main server block:
server {
    listen 443 ssl http2;
    server_name example.com;
    # SSL configuration goes here
    # ...
    location ~ \.php$ {
        fastcgi_pass ...
    }
}

Когда мы вводим Varnish в качестве слоя кэширования, нам необходимо внести следующие изменения:

  • настроить основной блок сервера для прослушивания произвольного порта, например 8080
  • представить блок сервера терминации TLS

Первое изменение довольно тривиально. В главном server блоке удалите конфигурацию SSL и измените ее listen 443 ssl; на listen 8080;:

# the main server block:
server {
    listen 8080;
    server_name example.com;
    # SSL configuration goes here
    # ...
    location ~ \.php$ {
        fastcgi_pass ...
    }
}

Затем добавьте новый завершающий блок TLS server {} следующим образом:

upstream varnish {
  server 127.0.0.1:6081;
  keepalive 64;
}

server {
    listen 443 ssl http2;
    # SSL configuration goes here
    # ...
    server_name example.com;
    location / {
        proxy_pass http://varnish;
        proxy_buffering off;
        proxy_request_buffering off;
        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;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header Ssl-Offloaded "1";
    }
}

Далее мы будем использовать модуль реального IP NGINX, чтобы гарантировать, что NGINX доверяет IP-адресу конечного посетителя из Varnish и не включает порт Varnish при выполнении перенаправлений.
Создать /etc/nginx/conf.d/varnish.conf с содержимым:

set_real_ip_from 127.0.0.1;
port_in_redirect off;
absolute_redirect off;

Еще одно изменение, необходимое в вашей конфигурации NGINX, — это сообщить PHP о нашем фактическом уровне безопасности спереди.
Для этого найдите блок обработчика PHP и измените его следующим образом:

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param HTTPS on;  # <-- add this
    fastcgi_param SERVER_PORT 443;  # <-- add this
    fastcgi_pass unix:/path/to/your/php-fpm.sock;
}

Это необходимо, поскольку WordPress не поддерживает чтение файлов X-Forwarded-Proto. При явной установке этих параметров FastCGI WordPress будет знать, что он работает через https://,
и не будет выполнять ненужные перенаправления.

Итак, теперь вы можете перезагрузить конфигурацию NGINX, запустив systemctl reload nginx.
Любой запрос, поступающий на сайт, будет перенаправлен на HTTPS, который маршрутизируется через Varnish в качестве уровня кеширования.

Шаг 6. Тестирование и мониторинг

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

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

Чтобы легко проверить, нормально ли кэшируется ваш сайт в Varnish, проверьте заголовки ответов и найдите заголовок X-Varnish или Age:

  • Заголовок Age сообщает вам, как долго Varnish хранит страницу в кеше. Положительное значение указывает на попадание в кэш, а 0 означает промах в кэше.
  • Включает X-Varnish одно или два числа. Первое число — это идентификатор входящего запроса, а второе число — это идентификатор ответа. Два числа в заголовке означают, что запрос является кэшированным. А одно число указывает на промах в кэше.

Улучшение коэффициента попадания в кэш Varnish

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

1. Недружественные к кешу плагины

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

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

Чтобы проверить, есть ли у вас такой плагин, просмотрите заголовки ответов вашего веб-сайта и найдите файлы Set-Cookie.
Если Varnish увидит такой ответ от WordPress, такая страница не может быть кэширована, поскольку Varnish просто гарантирует, что пользовательские данные (которыми являются файлы cookie) не передаются между пользователями.

2. Отслеживание файлов cookie

Если вы используете Google Analytics или любой другой вид отслеживания для своего веб-сайта, скорее всего, они полагаются на файлы cookie для сохранения своих данных.
Если для вашего веб-сайта установлен файл cookie, браузер будет отправлять его при каждом последующем запросе.

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

Как с этим бороться и улучшить кешируемость?

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

Решение заключается в добавлении файлов cookie WordPress в белый список в вашей конфигурации VCL и удалении любых других файлов cookie. Это можно сделать, добавив в блок следующее vcl_recv {... }:

if (req.http.Cookie !~ "comment_author_|wordpress_(?!test_cookie)|wp-postpass_|woocommerce") {
    # no essential cookies, nuke the rest!
    unset req.http.cookie;
}

Не забудьте применить обновленную конфигурацию, запустив systemctl reload varnish.

3. Ненужные параметры запроса

Если вы используете AMP со своим WordPress, скорее всего, страницы AMP содержат специальные URL-адреса noamp в нижнем колонтитуле. На самом деле они абсолютно идентичны стандартным страницам вашего сайта и отличаются только URL-адресом, заканчивающимся на ?noamp=mobile. Чтобы улучшить кэшируемость, вы можете добавить это в свой раздел vcl_recv:

# Strip "?noamp=mobile" from URL
set req.url = regsub(req.url, "\?noamp=mobile$", "");

Заключение

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

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