Страничное кеширование в WordPress |
Здравствуйте, гость ( Вход | Регистрация )
Страничное кеширование в WordPress |
22.2.2015, 21:55
Сообщение
#1
|
|
Администратор Группа: Главные администраторы Сообщений: 14349 Регистрация: 12.10.2007 Из: Twilight Zone Пользователь №: 1 |
PHP*, WordPress* В последнее время на Хабре появилось довольно много постов по данной теме, но по своей сути их можно назвать: «Смотрите, я поставил Varnish / W3 Total Cache и держу миллион запросов на «Hello world» страничке». Данная же статья рассчитана больше на гиков, желающих познать, как же это все работает и написать собственный плагин для страничного кеширования. Зачем? Стандартный вопрос, который вознивает у каждого разработчика перед созданием Приступим Какие инструменты предоставляет нам WordPress? Как все знают, данная CMS позволяет легко расширять свою функциональность с помощью плагинов, но не все знают, что есть несколько типов плагинов:
advanced-cache.php Для того, чтобы данный плагин начал функционировать, его нужно поместить в директорию wp-content, а в wp-config.php добавить строку: define('WP_CACHE', true); Если заглянуть в код WordPress, то можно увидеть, что данный скрипт подгружается на раннем этапе загрузки платформы. // wp-settings.php:63 // For an advanced caching plugin to use. Uses a static drop-in because you would only want one. if ( WP_CACHE ) WP_DEBUG ? include( WP_CONTENT_DIR . '/advanced-cache.php' ) : @include( WP_CONTENT_DIR . '/advanced-cache.php' ); Также, после загрузки ядра, CMS попытается вызвать функцию wp_cache_postload(), но о ней позже. // wp-settings.php:226 if ( WP_CACHE && function_exists( 'wp_cache_postload' ) ) wp_cache_postload(); Хранилище Для хранения кеша лучше всего использовать быстрые хранилища, так как от их скорости напрямую зависит скорость отдачи контента из кеша. Я бы не советовал использовать MySql или файловую систему, гораздо лучше с этим справятся Memcached, Redis или другие хранилища, использующие оперативную память. Мне лично нравится Redis, так как им довольно просто пользоваться, имеет хорошие показатели скорости чтениязаписи и как приятный бонус — сохраняет копию данных на жесткий диск, что позволят не терять информацию при перезагрузке сервера. $redis = new Redis(); // подключение к серверу $redis->connect( 'localhost' ); // сохранить данные $value под ключем $key на время $timeout $redis->set( $key, $value, $timeout ); // получить данные по ключу $key $redis->get( $key ); // удалить данные по ключу $key $redis->del( $key ); Разумеется это не полный перечень методов, весь список API можно изучить на официальном сайте, но для большинства задач этого достаточно. Если на сайте используется прокаченный обьектный кеш (object-cache.php), то имеет смысл использовать его API: wp_cache_set( $key, $value, $group, $timeout ); wp_cache_get( $key, $group ); wp_cache_delete( $key, $group ); Простейшое страничное кеширование Код нарочно упрощен, многие проверки убраны, дабы не путать читателя лишними конструкциями и сфокусироватся на логике самого кеширования. В файл advanced-cache.php прописываем: // если как хранилище используется обьектный кеш, то его нужно инициализировать вручную, // поскольку на данном этапе загрузки он еще не загружен wp_start_object_cache(); // формируем ключ // чаще всего это URL страницы $key = 'host:' . md5( $_SERVER['HTTP_HOST'] ) . ':uri:' . md5( $_SERVER['REQUEST_URI'] ); // берем данные из кеша по ключу if( $data = wp_cache_get( $key, 'advanced-cache' ) ) { // если данные существуют, отображаем их и завершаем выполнение $html = $data['html']; die($html); } // если данных нет, продолжаем выполнение // не сохраняем в кеш запросы админ панели if( ! is_admin() ) { // перехватываем буфер вывода ob_start( function( $html ) use( $key ) { $data = [ 'html' => $html, 'created' => current_time('mysql'), 'execute_time' => timer_stop(), ]; // после генерации страницы сохраняем данные в кеш на 10 минут wp_cache_set($key, $data, 'advanced-cache', MINUTE_IN_SECONDS * 10); return $html; }); } Все, вы получили простейший рабочий страничный кеш, теперь рассмотрим каждый участок детальнее. Создание ключа$key = 'host:' . md5( $_SERVER['HTTP_HOST'] ) . ':uri:' . md5( $_SERVER['REQUEST_URI'] );В данном случае ключем является URL страницы. Использование глобальной переменной $_SERVER и хеширования нельзя назвать лучшей практикой, но для простого примера подойдет. Советую использовать разделяющие участки строки как «host:» и «uri:», так как их удобно использовать в регулярных выражениях. Например получить все ключи по определенному хосту: $keys = $redis->keys( 'host:' . md5( 'site.com' ) . ':*' ); Выдача из кеша // берем данные из кеша по ключу if( $data = wp_cache_get( $key, 'advanced-cache' ) ) { // если данные существуют, отображаем их и завершаем выполнение $html = $data['html']; die($html); }Тут все просто, если кеш уже создан, то выдаем его пользователю и завершаем выполнение. Сохранение в кеш PHP функция ob_start перехватывает весь последующий вывод в буфер и позволяет обработать его в конце работы скрипта. Простыми словами мы получаем весь контент сайта в переменной $html.ob_start( function( $html ) { // $html - HTML код готовой страницы return $html; } Далее сохраняем данные в кеш:$data = [ 'html' => $html, 'created' => current_time('mysql'), 'execute_time' => timer_stop(), ]; wp_cache_set($key, $data, 'advanced-cache', MINUTE_IN_SECONDS * 10); Есть смысл сохранять не только HTML, но и прочую полезную информацию: время создания кеша и тд. Очень рекомендую сохранять HTTP заголовки, хотя бы Content-Type и посылать их при выдаче из кеша. Совершенствуем В примере выше мы использовали функцию is_admin() для исключения кеширования админ панели, но данный способ не очень практичен по двум причинам:
Наилучшим решением для простого сайта будет вообще не использовать кеш для залогиненых пользователей (администраторов). Так как advanced-cache.php выполняется до полной загрузки ядра, мы не можем пользоваться функцией is_user_logged_in() , но можем определить наличие аутентификации по cookie (как известно WordPress не использует сессии). // проверяем наличие cookie wordpress_logged_in_* $is_logged = count( preg_grep( '/wordpress_logged_in_/', array_keys( $_COOKIE ) ) ) > 0; // сохраняем кеш только не залогиненых пользователей if( ! $is_logged ) { ob_start( function( $html ) use( $key ) { // .... return $html; }); } Усложняем задачу Допустим, наш сайт отдает разный контент для пользователей из разных регионов или стран. В данном случае ключем кеша должен быть не только URL страницы, но и регион: $region = get_regeon_by_client_ip( $_SERVER['REMOTE_ADDR'] ); $key = 'host:' . md5( $_SERVER['HTTP_HOST'] ) . ':uri:' . md5( $_SERVER['REQUEST_URI'] ) . ':region:' . md5( $region ); По данному принципу мы можем формировать разный кеш разным группам пользователям по любым параметрам. wp_cache_postload() Данная функция вызывается после загрузки ядра и ее тоже удобно использовать в некоторых случаях. По опыту скажу, что такой вариант работает гораздо стабильней:function wp_cache_postload() { add_action( 'wp', function () { ob_start( function( $html ) { // ... return $html; }); }, 0); } На момент вызова wp_cache_postload(), функция add_action уже существует и ей можно пользоваться. Бывают ситуации, когда для формирования ключа кеша нужны данные, которые невозможно получить из cookie, IP и прочих доступных на этапе инициализации ресурсов. Например нужно генерировать индивидуальный кеш для каждого пользователя (иногда это имеет смысл).function wp_cache_postload() { $key = 'host:' . md5( $_SERVER['HTTP_HOST'] ) . ':uri:' . md5( $_SERVER['REQUEST_URI'] ) . ':user:' . get_current_user_id(); if( $data = wp_cache_get( $key, 'advanced-cache' ) ) { $html = $data['html']; die($html); } add_action( 'wp', function () { ob_start( function( $html ) { // ... return $html; }); }, 0); } Как видно в примере, вся логика помещена в тело wp_cache_postload и тут уже доступны все функции платформы, включая get_current_user_id(). Данный вариант немного медленней предыдущего, но мы получаем безграничные возможности для тонкой настройки страничного кеша. О чем не стоит забывать
Заключение Нет ничего сложного в написании собственного страничного кеширования. Разумеется в этом нет смысла для типичного сайта, но если вы породили монстра — данный материал должен оказаться полезным. Original source: habrahabr.ru (comments, light). Читать дальше -------------------- |
|
|
26.8.2016, 1:54
Сообщение
#2
|
|
Newbie Группа: Пользователи Сообщений: 5 Регистрация: 1.8.2013 Пользователь №: 1647 |
Есть с WordPress очень просто работать, потому что в интернете очень много полезных инструкий и советов по созданию своего сайта. Я уже попробовал, и получилось достаточно быстро создать простой одностраничный сайт. Сейчас хочу сделать лендинг, как тут описано https://codeby.net/wordpress/kak-sozdat-len...g-na-wordpress/ . Это уже сложнее, но со временем должно все получится. А если нет - буду просить помощи на форуме
|
|
|
Текстовая версия | Сейчас: 29.1.2025, 23:49 | |