Ускоряем WordPress с NGINX и умным кэшем на Varnish
Зачем это нужно
Водпресс сделан довольно гибким, чтобы как можно больше разработчиков могло его поддерживать и писать к нему всяческие расширения. Однако это негативно сказывается на производительности. Чтобы отрендерить страницу, Водпрессу приходится пробираться через тонну строчек кода и сделать кучу SQL запросов к базе.
Обычно для Водпресса используют такой стек: Apache+PHP+MySQL+какой-нибудь кэширующий плагин внутри CMS. Это популярное решение, но не сильно быстрое и хорошо работает только пока трафик маленький. Для хайлод проектов на Вордпрессе такой стек не подойдет — будет есть много ресурсов и, как следствие, увеличивать затраты на оборудование.
Хорошая новость в том, что Вордпресс чаще используют для создания статичного контента. В этом смысле, нет никакого смысла тратить ресурсы на перерендеривание страницы при каждом клиентском запросе. Чтобы этого не делать, я предлагаю отдавать статику для всех анонимных пользователей, а для авторизованных пользователей или динамики направлять запросы к балансировщику нагрузки.
В качестве кэширующего сервера я взял Варниш 4.0. Он быстрый, гибкий и прекрасно справится с моей задачей.
Архитектура
На фронтенд я поставил NGINX, Varnish как кэширующий сервер «позади» NGINX, поднял несколько нод с NGINX+php-fpm и повесил на них Haproxy в качестве балансировщика нагрузки. Я ожидал получить такую картину:
Как работает стек
Nginx принимает запросы с клиента и проксирует их к Варнишу. Потом Варниш проверяет: если у него есть закэшированная страница, он отдает её, если нет — отправляет запрос к Хапрокси, который, в свою очередь, распределяет нагрузку между несколькими нодами.
В нодах стоит стэк из NGINX в FastCGI mode в кластерном варианте конфигурации, что позволяет ему отправлять запросы к ближайшему PHP серверу. В качестве базы я взял MariaDB.
Чтобы сделать такой же стек с помощью D2C понадобятся следующие сервисы:
Сервисы
- Nginx
- Custom Docker service для Varnish
- Haproxy
- NginxCluster
- Php-FPM
- MariaDB
Плагины Вордпресса
- Varnish HTTP Purge plugin, чтобы обновлять кэш Варниша при добавлении постов.
- Fake press plugin. Я хотел протестировать стек не на пустом Водпрессе, а с данными. Этот плагин помог мне сгенерировать несколько сотен постов, тегов и категорий.
Итак, собираю стек
1. Создаю хосты. Для этой статьи, я создал 3 демо-хоста на AWS. Вы можете использовать собственные.
2. Выбираю SQL базу. Я предлагаю взять MariaDB. В этом примере Мария была в StandAlone конфигурации для чистоты эксперимента и с дефолтными настройками.
3. Разворачиваю PHP-FPM. На этом этапе понадобится Вордпресс. Его можно развернуть тремя способами: из Гита, загрузить по ссылке или прикрепить .zip/.tar архив. Я использовал официальный git репозиторий WordPress.
4. Ставлю NginxCluster. Для стэка понадобится Nginx Cluster в FastCGI mode. В D2C он уже настроен на работу с PHP-FPM, так что особо ничего не придется делать.
5. Добавляю балансировщик нагрузки для нескольких инстансов NGINX.В D2C это будет Haproxy с алгоритмом round robin.
6. Разворачиваю Varnish cache из Докер-образа. Пока в D2C еще не добавили готового сервиса для Варниша, так что приходится его разворачивать из Докер-образа.
В настройках сервиса указываю в полях Docker Image "debian", version "jessie" и прописываю на выполнение следующею команду:
apt-get install wget wget -qO- https://packagecloud.io/install/repositories/varnishcache/varnish51/script.deb.sh | bash apt-get install varnish
Эта команда скачивает образ и устанавливает его.
Потом прописываю в поле "Start Command":
varnishd -j unix,user=vcache -F -f /etc/varnish/default.vcl -s malloc,100m -a 0.0.0.0:80
Команда запускает Варниш от пользователя "vcache", выделяет 100MB оперативной памяти и определяет путь к конфигурационному файлу и порт, который должен слушать Варниш.
Потом делаю записи в конфигурационный файл, который создаю по следующему адресу: "/etc/varnish/default.vcl". Пока что он будет содержать немного настроек:
vcl 4.0; backend default { .host = "web alias"; .port = "80"; }
"Web alias" это имя веб-сервера, на который Варниш будет отправлять запросы. В нашем стеке мы пропишем алиас Хапрокси.
Пока что это базовый конфиг. После того, как я добавлю все необходимые сервисы, я вернусь к нему для тонкой настройки.
6. Ставлю простой Nginx в качестве фронтенда. Он будет обслуживать SSL. Здесь достаточно добавить сервис и выбрать Варнишь в зависимостях, а затем сгенерировать https конфигурацию для SSL.
После добавления нужных сервисов получилась такая картина:
Теперь пора настроить инфраструктуру.
Настраиваю Varnish
Конфигурация выше мне не подходит. Надо её доработать. Посмотрим, что можно сделать.
Для начала, надо указать хосты, с которых Варниш будет получать запросы на очистку:
acl purge { "host-alias1"; "host2-alias2"; "host3-alias3"; ... }
Вместо хостов надо прописать алиасы ближайших к Варнишу сервисов. В этом стеке я указал алиасы Nginx на фронтенде и Хапрокси.
Затем нужно слегка доработать алгоритм, по которому будет работать с кэшем Варниш. Чтобы не выкладывать весь длинный список доработок, я просто дам ссылку на полный конфиг Варниша.
Конфигурация Varnish для работы с Wordpress
Почти сделано. Осталось поставить Varnish HTTP Purge plugin, чтобы посылать запросы Варнишу на очистку кэша при добавлении и изменении материалов и наш стек готов.
Результаты тестов
Напоследок несколько ab тестов двух наших t2.micro Amazon EC2 инстансов. Я поставил oncurrency level 100 и 1000 запросов всего.
Без кэширования
С кэшированием
Один микро хост на Амазоне обработал 1000 запросов одновременными порциями по 100 штук за 48 секунд, на обработку одного запроса в среднем ушло 154 миллисекунды. Наш стек сократил эти цифры примерно на порядок, получилось 8 секунд на тест и 8 миллисекунд в среднем на запрос.
Как видно, новый стек дал такой не слабый прирост производительности :-)
Полезные ссылки
- Varnish HTTP Purge plugin для очистки кэша при добавлении постов.
- Fake press plugin для генерации рыбных статей.
- Полный Varnish config
- PAAS платформа D2C