Кэшируем Wordpress средствами Nginx
Wordpress далеко не самая производительная платформа для ведения блогов, и крупные сайты, как правило, используют кэширование для ускроения его работы. Для wordpress, есть много популярных дополнений реализующих кэширование, но все они на мой взгляд довольно осложненные, и, как правило, требуют либо установки дополнительного программного обеспечения, такого как, например, Varnish или memcached, либо перекладывают кэширование на плечи PHP который тоже производительным не назовешь. В этом посте я расскажу как настроить кэширование wordpress средствами nginx, без установки дополнительного ПО.
В nginx есть FastCGI модуль который предоставляет директивы, позволяющие кэшировать ответ от fastcgi. Использование данного модуля избавляет нас от необходимости использовать сторонние средства кэширования. Модуль так же позволяет нам не кэшировать часть ресурсов опираясь на различные параметры запроса, такие как, например: тип (GET, POST), куки, адрес страницы и другие. Сам модуль умеет исключительно добавлять в кэш, но не умеет его очищать или удалять отдельные записи из него. Без очистки кэша при добавлении, редактировании и добавлении комментария к посту кэш не будет обновляться, и сделанные изменения будут видны только с большой задержкой, поэтому для очистки кэша мы будем использовать сторонний nginx модуль - nginx_cache_purge.
Настройка nginx
В большинстве современных дистрибутивов nginx уже собран с модулем ngx_cache_purge
, но на всякий случай проверим, что он присутствует. В консоли выполним:
nginx -V 2>&1 | grep -o nginx-cache-purge
Если после выполнения команды вы видите nginx-cache-purge
, то значит можно продолжать. Если после выполнения команды ничего не появилось, то у вас вероятно какой-то из старый дистрибутивов ubuntu, в котором nginx собран без поддержки этого модуля. В данном случае необходимо переустановить nginx из стороннего ppa:
sudo add-apt-repository ppa:rtcamp/nginx
sudo apt-get update
sudo apt-get remove nginx*
sudo apt-get install nginx-custom
Настроим nginx. Откроем файл с настройками виртуального хоста, и приведем его к примерно такому содержимому:
fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
# Upstream to abstract backend connection(s) for php
upstream php {
server unix:/var/run/php5-fpm.sock fail_timeout=0;
}
server {
listen 80;
server_name .example.com;
root /var/www/example.com/html;
index index.php;
error_log /var/www/example.com/log/error.log;
access_log /var/www/example.com/log/access.log;
set $skip_cache 0;
# POST requests and urls with a query string should always go to PHP
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
# Don't cache uris containing the following segments
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
set $skip_cache 1;
}
# Don't use the cache for logged in users or recent commenters
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
set $skip_cache 1;
}
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass php;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 60m;
}
location ~ /purge(/.*) {
allow 127.0.0.1;
deny all;
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
}
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off;
log_not_found off;
expires max;
}
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Deny access to uploads that aren’t images, videos, music, etc.
location ~* ^/wp-content/uploads/.*.(html|htm|shtml|php|js|swf)$ {
deny all;
}
# Deny public access to wp-config.php
location ~* wp-config.php {
deny all;
}
}
Разумеется, параметры root
, server_name
, access_log
, error_log
необходимо исправить согласно тому, как у вас все настроенно. В строке fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;
мы говорим nginx, что хранить кэш нужно в директории /var/run/nginx-cache/
, зону памяти называем WORDPRESS
, максимальный размер кэша устанавливаем в 100 мегабайт и таймер сброса из-за неактивности устанавливаем в 60 минут. Приятным бонусом подобной конфигурации является то, что если по каким-то причинам наш PHP бекэнд перестает работать, nginx продолжит отдавать закэшированные страницы.
Настройка Wordpress
Сам nginx не знает, когда нужно очищать кэш, поэтому необходимо установить дополнение для wordpress, которое будет автоматически очищать кэш после изменений. Ставим дополнение Nginx Helper, активируем его, переходим в его настройки и включаем опцию Enable purge.
Остальные настройки можно не трогать, по-умолчанию дополнение настроено довольно оптимально.
Финальные шаги
Проверяем, что не допустили ошибок в конфигурации nginx:
nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
И если все хорошо - перезагружаем его:
systemctl reload nginx
Заходим на любую страницу, и проверяем что nginx добавил её в кэш:
ls -la /var/run/nginx-cache
Дополнительно: помещаем кэш nginx в ramdisk (tmpfs)
Сейчас у нас кэширование настроено, но кэш хранится на жестком диске, что не является хорошим решение. Оптимальнее будет смонтировать директорию с кэшем nginx в память. Для этого откроем /etc/fstab
, и добавим туда:
tmpfs /var/run/nginx-cache tmpfs nodev,nosuid,size=110M 0 0
Если в настройках nginx вы указали больший размер кэша, то параметр size
необходимо изменить в соответствии с указанным размером кэша, плюс небольшой запас.
Сразу смонтируем директорию в память:
sudo mount -a
Теперь при каждой загрузке системы, директория /var/run/nginx-cache
будет помещаться в память, что должно уменьшить время отдачи страницы.
Заключение
Не стоит рассчитывать на данный способ как на панацею. Интерпретатор PHP как я уже выше писал, нельзя назвать быстрым, да и сам Wordpress довольно большой и "тяжелый". Если страницы нет в кэше, или она редко запрашивается, то nginx всё равно сначала будет обращаться к не самому производительному бекэнду. Однако в целом, кэширование даст возможность вашему серверу немного расслабиться на генерации популярных постов, и в моменты публикации нового поста.
Это далеко не единственный способ ускорить ваш wordpress блог. Существует ещё масса других техник, о которых я напишу позже.