Ускоряем свой WordPress-сайт с помощью Pound, Varnish, Nginx и mod_pagespeed
Подавляющее большинство онлайн-статей, посвященных ускорению WordPress-сайта, рассматривают (или хотя бы упоминают) использование плагина W3 Total Cache (или W3TC, если коротко). Это верно, ведь указанный плагин является полезным и практичным универсальным решением, позволяющим ускорить работу WordPress-сайта, проведя относительно небольшой объем работ.
Однако я не являюсь сторонником универсальных решений, главным образом потому, что они добавляют лишнюю сложность и могут приводить к проблемам совместимости (если использовать их в сборке с разными плагинами); также могут появляться сложности и с их обновлением.
Именно по этой причине я решил подыскать альтернативы, которые помогают ускорить работу нашего (защищенного) WordPress-сайта, и друзья посоветовали мне взглянуть на mod_pagespeed, который оказался идеальным решением для того, чтобы сделать наш WordPress-сайт действительно быстрым, причем с минимальными усилиями.
Требования
Эта статья предполагает, что у вас имеются по крайней мере минимальные знания Linux (все наши примеры основаны на Ubuntu), вы знаете, как использовать shell, и, что более важно, ваш сайт расположен на вашем собственном VPS. Виртуальный хостинг не подойдет для этого, поскольку нам нужна будет настроенная версия nginx, поддерживающая mod_pagespeed.
Есть много хороших и относительно дешевых VPS-провайдеров, которые предлагают свои услуги. Я рекомендую в данном случае воспользоваться Digital Ocean.
Обратите внимание, что все команды, которые начинаются со знака доллара, описывают unix-команды; вам не требуется вводить этот доллар в командную строку.
Основные компоненты
Как следует из заголовка, нам понадобится установить на сервер некоторые программы; самая главная (для кэширования) называется Varnish, она сохраняет весь ваш HTML-вывод во временную папку на диске, что позволяет обходиться без постоянных запросов к WordPress. У этой программы, правда, имеется один недостаток – она не поддерживает SSL-терминацию, по причине чего нам и требуется Pound.
Два последних компонента, которые нам понадобятся – это Nginx (веб-сервер, как, к примеру, Apache) и PHP-FPM (менеджер процессов PHP), поскольку Nginx не поддерживает модули.
Естественно, вам нужно будет сгенерировать ключ сертификата и приобрести сертификат для своей сборки. Сертификаты начального уровня достаточно дешевые, некоторые из них стоят от $10/год, что позволяет легко их приобретать для своих целей.
Начало работы
Предположим, что у вас есть чистый, свежий VPS с SSH. Подсказка: если вы используете Linux или Mac OS на локальной машине, вы можете добавить следующий шорткат к ~/.ssh/config (создайте этот файл, если он не существует):
Host MyHost HostName [host-ip] Port [host-port] User [host user, usually root] IdentityFile [path/to/your/ID_RSA, usually ~/.SSH/ID_RSA]
В итоге вы сможете запускать следующую команду для входа в шелл вашего сервера: $ ssh MyHost
После того как вы войдете в командную оболочку, вы сможете установить все необходимые компоненты через менеджер пакетов, в нашем случае: apt-get.
Выполняем следующую команду:
$ sudo apt-get install php5-fpm php5-cli php5-mysql varnish pound mariadb-server-5.5 unzip
Вам предложат дважды ввести root-пароль для MariaDB, которая является прямой заменой MySQL. Мы не будем устанавливать Nginx на данном этапе, поскольку версия, которая идет по умолчанию, не поддерживает mod_pagespeed, необходимый нам, поэтому мы установим его вручную. Чтобы сделать это, перейдите к официальной документации и выполните все шаги руководства, правда, с одним исключением. Замените строку:
./configure --add-module=$HOME/ngx_pagespeed-release-${NPS_VERSION}-beta
На следующую:
./configure --add-module=$HOME/ngx_pagespeed-release-${NPS_VERSION}-beta --with-http_gzip_static_module --with-http_realip_module
Это позволит нам включить модули для GZIP-сжатия статичных файлов и отслеживания корректных IP-адресов в вашей сборке WordPress. После того, как вы сделаете это, вам нужно будет установить Nginx в /usr/local/nginx/.
Если вы попытаетесь посетить URL (или IP) вашего сервера на данном этапе, то вы ничего не увидите, поскольку мы пока не настраивали все эти компоненты. После того, как мы это сделаем, схема взаимодействия между компонентами вашего сервера будет выглядеть следующим образом:
Pound
Давайте начнем с компонента outermost, который работает с двумя стандартными портами, 80 и 443 (HTTP и HTTPS, соответственно). Отредактируйте файл /etc/pound/pound.cfg и поместите в него следующий контент:
User "www-data" Group "www-data" LogLevel 1 Alive 30 Control "/var/run/pound/poundctl.socket" ListenHTTP Address 0.0.0.0 Port 80 # This part makes sure you redirect all HTTP traffic to HTTPS Service HeadRequire "Host: yourdomain.com" Redirect "https://yourdomain.com" End End ListenHTTPS HeadRemove "X-Forwarded-Proto" AddHeader "X-Forwarded-Proto: https" Address 0.0.0.0 Port 443 Cert "/etc/ssl/yourdomain.com/yourdomain.com.pem" # This service removes the WWW-part Service HeadRequire "Host: www.mydomain.com" Redirect "https://yourdomain.com" End # The main service which passes requests to Varnish Service HeadRequire "Host: yourdomain.com" BackEnd Address 127.0.0.1 # 6081 is the default Varnish port Port 6081 End End End
Перед тем, как проводить рестарт Pound с новой конфигурацией, вам нужно будет добавить файл PEM-сертификата в определенную папку; этот файл вы можете создать, следуя представленным инструкциям. Также вам нужно будет отредактировать /etc/default/pound и задать startup=1.
Готово. Pound теперь сконфигурирован, и после запуска $ service pound restart (для Ubuntu, другие дистрибутивы могут иметь свои команды для управления службой) вы сможете посетить сконфигурированный домен. Естественно, вы получите ошибку (503 Service Unavailable), однако это не страшно, поскольку мы еще не все настроили.
Varnish
Далее нам нужно будет сконфигурировать Varnish. Редактируем файл /etc/varnish/default.vcl и помещаем в него следующий код (удаляем все остальное):
backend default { .host = "127.0.0.1"; .port = "8080"; } acl purge { "127.0.0.1"; "localhost"; } sub vcl_recv { if (req.request == "PURGE") { if (!client.ip ~ purge) { error 405 "Not allowed."; } ban("req.url ~ "+req.url+" && req.http.host == "+req.http.host); error 200 "OK"; } # only using one backend set req.backend = default; # set standard proxied ip header for getting original remote address set req.http.X-Forwarded-For = client.ip; # logged in users must always pass if( req.url ~ "^/wp-(login|admin)" || req.http.Cookie ~ "wordpress_logged_in_" ){ return (pass); } # don't cache search results if( req.url ~ "?s=" ){ return (pass); } # always pass through posted requests and those with basic auth if ( req.request == "POST" || req.http.Authorization ) { return (pass); } # else ok to fetch a cached page unset req.http.Cookie; return (lookup); } sub vcl_fetch { # remove some headers we never want to see unset beresp.http.Server; unset beresp.http.X-Powered-By; # only allow cookies to be set if we're in admin area - i.e. commenters stay logged out if( beresp.http.Set-Cookie && req.url !~ "^/wp-(login|admin)" ){ unset beresp.http.Set-Cookie; } # don't cache response to posted requests or those with basic auth if ( req.request == "POST" || req.http.Authorization ) { return (hit_for_pass); } # only cache status ok if ( beresp.status != 200 ) { return (hit_for_pass); } # don't cache search results if( req.url ~ "?s=" ){ return (hit_for_pass); } # else ok to cache the response set beresp.ttl = 24h; return (deliver); } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; } else { set resp.http.X-Cache = "MISS"; } unset resp.http.Via; unset resp.http.X-Varnish; } sub vcl_hit { if (req.request == "PURGE") { purge; error 200 "OK"; } } sub vcl_miss { if (req.request == "PURGE") { purge; error 404 "Not cached"; } } sub vcl_hash { hash_data( req.url ); if ( req.http.host ) { hash_data( regsub( req.http.host, "^([^.]+.)+([a-z]+)$", "12" ) ); } else { hash_data( server.ip ); } # ensure separate cache for mobile clients (WPTouch workaround) if( req.http.User-Agent ~ "(iPod|iPhone|incognito|webmate|dream|CUPCAKE|WebOS|blackberry9ddd)" ){ hash_data("touch"); } return (hash); }
Я не буду сейчас раскрывать здесь все детали работы кода, поскольку официальная документация Varnish делает это гораздо лучше. Упомяну лишь про три вещи, которые здесь важны. Во-первых, это строка, которая позволяет нам очистить (purge) кэш (удалить его), что очень полезно в WordPress, поскольку в таком случае обновленные участки автоматически инициируют удаление кэша. Есть несколько плагинов для этого, мы используем Better WP Varnish, но вы можете вполне воспользоваться и любым другим.
Во-вторых, нужно упомянуть про обработку cookie. Данная конфигурация не позволяет залогиненным пользователям видеть кэшированные версии компонентов WordPress, что помогает осуществлять дебаггинг и предпросмотр.
Наконец, мы используем произвольный заголовок (X-Cache), который равняется либо HIT, либо MISS, поэтому вы можете легко проводить отладку и видеть, передал ли Varnish кэшированную версию (HIT) или нет.
Как в случае с Pound, нужно провести рестарт Varnish, чтобы загрузить новую конфигурацию: $ service varnish restart.
Nginx и mod_pagespeed
Итак, мы почти добрались до конца. Заключительный фрагмент нашего пазла – это Nginx. Поскольку мы не использовали менеджер пакетов для его установки, нам нужно будет сначала выполнить init script, который зарегистрирует Nginx в качестве daemon (программа или процесс, который запускается в фоновом режиме). Чтобы сделать это, выполним следующие команды:
$ cd /etc/init.d $ wget https://raw.githubusercontent.com/JasonGiedymin/nginx-init-ubuntu/master/nginx $ chmod +x nginx $ update-rc.d nginx defaults
Код приведет к загрузке скрипта инициализации, сделает его исполнимым (поскольку это, по существу, программа) и зарегистрирует его в операционной системе – таким образом, он сможет запуститься во время начальной загрузки.
Как только это будет сделано, мы должны будем настроить Nginx, отредактировав файл /usr/local/nginx/conf/nginx.conf. Найдите первый блок server в файле и замените его код на следующий (мы отталкиваемся от предположения, что ваша система WordPress установлена в /srv/www/yourdomain.com):
server { listen 8080; server_name test.com; root /srv/test.com; index index.php index.html; location / { try_files $uri $uri/ /index.php?$args; } location ~ .php$ { try_files $uri /index.php; include fastcgi_params; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_index index.php; } pagespeed On; pagespeed ModifyCachingHeaders on; # Needs to exist and be writable by nginx. pagespeed FileCachePath "/var/cache/ngx_pagespeed/"; pagespeed LoadFromFile "https://yourdomain.com" "/srv/yourdomain.com"; pagespeed MapOriginDomain "http://localhost" "https://yourdomain.com"; pagespeed EnableFilters rewrite_css,combine_css,trim_urls; pagespeed DisableFilters sprite_images,convert_jpeg_to_webp,convert_to_webp_lossless; }
Верхняя половина – это просто базовая конфигурация для нашего виртуального хоста, который включает перезапись и делегирует PHP-обработку PHP-FPM.
Здесь нам интересна будет часть pagespeed. После ее включения нам нужно правильным образом задать URL-адреса, чтобы mod_pagespeed знал, где применять свою «магию». Затем мы включаем/отключаем разные фильтры; это уже зависит от ваших требований, как именно mod_pagespeed должен изменять/оптимизировать ваш HTML. Я предпочитаю те фильтры, которые автоматически объединяют CSS и Javascript файлы, оптимизируют изображения и переименовывают их в соответствии со временем их последнего изменения.
Есть одно предостережение: убедитесь в том, что вы отключили фильтр convert_jpeg_to_webp. Название фильтра говорит о том, что он делает. Проблема с ним возникает из-за использования Varnish. Если самый первый посетитель вашего сайта будет использовать Chrome, Varnish отправит запрос к Nginx, и тот передаст изображения в формате WEBP, забив ими кэш. Все последующие посетители получат эту кэшированную версию, однако WEBP не слишком широко поддерживается браузерами, в итоге пользователи с другими браузерами могут не увидеть изображений!
Теперь настало время проверить, были ли наши усилия плодотворными; сделайте рестарт Nginx для загрузки новой конфигурации ($ service nginx restart) и посетите сайт. О да! Скорее всего, вы увидели совсем не то, что ожидали, верно? Произошло это по той причине, что Varnish уже был запущен, и, скорее всего, передал ошибочную версию, поскольку вы посещали сайт ранее. Исправить это легко: просто очистите весь кэш Varnish ($ varnishadm “ban req.url ~ /”). В итоге вы увидите корректный вывод:
Чтобы проверить корректность, вы можете проинспектировать ответ локально: $ curl -i https://yourdomain.com. В ответе вы должны видеть два заголовка: X-Cache и X-Page-Speed, которые сигнализируют о том, что вы получили в свое распоряжение веб-сайт, работающий гораздо быстрее!
Что по поводу тестов производительности?
Мне задавали вопросы по поводу сравнительных тестов производительности, однако в данном случае я не считаю, что это имеет смысл. Есть много разных тестов Varnish, однако mod_pagespeed связан не только со скоростью (несмотря на свое название). Как следует из его документации, он может делать гораздо больше, к примеру, проводить оптимизацию вывода вашего сайта с позиций конкатенации файлов, их минификации и обслуживания.
Источник: wptavern.com