Ускорение работы Wordpress

12 декабря 2018

  • С одной стороны, Wordpress популярен среди вебмастеров благодаря низкому порогу вхождения и универсальности.
  • С другой стороны, Wordpress известен медленной скоростью работы.
    • Даже статические по сути страницы при каждом обращении к ним проходят через громоздкую систему генерации с выполнением большого количества PHP-кода и SQL-запросов.
  • При этом ускорение сайта с помощью кэширования в HTTP-акселераторе (например, Squid в режиме реверсивного прокси или Nginx) использовать нельзя:
    • страницы необходимо удалять из кэша, когда они меняются в Вордпрессе;
    • но Вордпресс не имеет стандартного способа сообщить HTTP-акселератору о таком изменении.
  • Поэтому для Вордпресса создано большое количество кэширующих плагинов — как взаимодействующих с HTTP-акселератором, так и реализующих всю логику внутри самого Вордпресса.
    • Главный недостаток плагинов второго типа — хотя количество выполняемого PHP-кода кардинально сокращается, сам факт его выполнения уже приводит к низкой производительности.
    • Cachify является плагином первого типа — за счёт взаимодействия с Nginx кэшированные страницы отдаются вообще без передачи запроса в PHP/WP/MySQL.
    • Благодаря этому производительность сайта на Вордпрессе на большинстве запросов удаётся поднять до производительности статического сайта.

Способ работы:

  • Wordpress сохраняет в Memcached всё содержимое, отдаваемое неавторизованным посетителям.
  • Nginx обращается к Wordpress'у только в том случае, если результат запроса не найден в Memcached.

Установка пакетов в Debian/Ubuntu:

  • Подразумевается, что уже используется связка Nginx + PHP-FPM
  • Cachify совместим только с акселератором APC — Xcache и прочие аналоги не поддерживаются.
  • Можно использовать nginx-full или nginx-extras, но не nginx-light, т.к. он собран без поддержки memcached
  • Итого:
  • apt-get -y install php-apcu php-memcached memcached nginx-full

Настройка Nginx для кэширования в Memcached:

  • Стандартная директива try_files $uri $uri/ /index.php?$args; переносится в отдельный location @nocache
  • На бывшее место try_files помещается запрос страницы из memcached, предваряемый длинным блоком исключений. Не кэшируются и перенаправляются в @nocache по коду 405 следующие запросы:
    • с параметрами;
    • с типом POST;
    • от авторизованных пользователей;
    • в админку.
  • Если страница не будет обнаружена в memcached, запрос также будет перенаправлен в @nocache — по коду 404.
  • Полный текст настроек см. в https://github.com/pluginkollektiv/cachify/blob/master/inc/setup/cachify.memcached.nginx.php

Проверка работы:

  • Посещаем несколько страниц сайта...
  • ..и смотрим, сохранились ли они в кэше:
  • echo stats items | netcat 127.0.0.1 11211
    echo stats cachedump 29 100 | netcat 127.0.0.1 11211

Альтернативный вариант — настройка Nginx для кэширования в APC:

  • Данный способ нами пока не протестирован, но его настройка выглядит намного проще — достаточно к каждой директиве fastcgi_pass, передающей запросы из Nginx в PHP-FPM, добавить строку с установкой переменной:
  • fastcgi_param PHP_VALUE auto_prepend_file=;
  • Прочие достоинства: не надо устанавливать memcached и php-memcached, вместо nginx-full можно использовать nginx-light
  • Недостаток: неясно, как просматривать кэш, чтобы убедиться в его работоспособности.
  • Полный текст настроек см. в https://github.com/pluginkollektiv/cachify/blob/master/inc/setup/cachify.apc.nginx.php

Ограничения:

  • Cachify предлагает добавлять в настройки Nginx строку «add_header X-Powered-By Cachify», но этого НЕ следует делать в том случае, если add_header уже используются на верхних уровнях, т.к. документация Nginx гласит: «Директивы наследуются с предыдущего уровня при условии, что на данном уровне не описаны свои директивы add_header.»
  • Сайт обязан работать либо только через http, либо только через https, т.к. страницы содержат абсолютные ссылки, но сохраняются в memcached без учёта протокола. С другой стороны, в https://github.com/pluginkollektiv/cachify/pull/22 пишут, что сейчас данная проблема уже решена. Тем не менее, принудительный редирект клиентов с HTTP на HTTPS можно выполнить в Nginx'e примерно так:
  • location / {
         if ($http_x_forwarded_proto != "https") {      # ..behind standard proxy?
        #if ($http_cf_visitor ~ '{"scheme":"http"}') {  # ..behind Cloudflare?
             return 301 https://$server_name$request_uri; # ..force redirect from HTTP to HTTPS
         }
    
  • При обновлениях ядра Вордпресса, тем и плагинов не забывайте сбрасывать кэш!
  • systemctl restart memcached


← Назад в Блог