БлогКэш страниц. Снижение нагрузки на сервер с помощью Memcache Storage Page Cache

Сегодня я хотел бы рассказать ещё об одном моём модуле, который позволяет серьёзно снизить нагрузку на сервер. Но перед тем, как я расскажу про сам модуль, мне хотелось бы начать с небольшого рассказа про работу кэша страниц для анонимов.

Page Cache в Drupal 7

Эту часть я разобью на 3 небольших ступени, каждую из которых необходимо полностью понимать.

Ступень первая. Ядро Друпала содержит механизм кэширования отображаемых html страниц для анонимных пользователей. Вполне разумно - какой смысл создавать каждый раз одну и ту же страницу, если можно сгенерировать её для одного анонима, а остальным отдавать уже готовый результат. В таком случае Друпал не будет каждый раз вызывать функцию для генерации и рендера страницы, а лишь заберёт страницу из кэша и сразу отдаст её пользователю.

Ступень вторая. В настройках производительности (/admin/config/development/performance) есть 2 настройки времени жизни кэша:

page_cache_1.png

Первая настройка - Минимальное время жизни кэша (cache lifetime). Если по прошествию этого периода был вызван сброс старого кэша, то будут удалены все старые и временные записи с кэшем из сегментов с блоками (cache_block) и страницами (cache_page). Здесь надо обратить внимание на сброс временного кэша, так как все сохраняемые в кэше страницы всегда помечаются как временные. Сброс старого кэша вызывается при любых действиях с контентом (как минимум это добавление/изменение/удаление любых материлов/комментариев/пользователей). Именно поэтому при работе с кэшем страниц рекомендуется выставлять значение этой настройки в какое-либо значение, отличное от начального. В противном случае каждое изменение контента будет тянуть за собой операции по очистке кэша.

Вторая настройка - Максимальное время. К сожалению, здесь перевод не отражает сути настройки. По-английски она называется более правильно - Expiration of cached pages, что переводится как "Время жизни кэшированных страниц". Однако даже знание правильного названия настройки не даст вам правильного понимания её работы. Она не отвечает за время жизни кэша страниц на вашем сайте. Она лишь выставляет заголовок Cache-Control: public, max-age= ' . $max_age, где $max_age - это и есть значение данной настройки. Этот заголовок даёт понять прокси серверу (например, Варнишу) когда надо обратиться к Друпалу за получением нового HTML текущей страницы, вместо того, чтобы отдавать её не доходя даже до PHP.

Ступень третья. Исходя из вышесказонно несложно сделать вывод, что за частоту сброса всего кэша, и в частности кэша страниц, отвечает настройка "Минимальное время жизни кэша", которая задаётся для всех сегментов кэша одинаково.

А теперь давайте представим вполне обыденную ситуацию: предположим, у нас есть новостной сайт, на котором достаточно часто (пускай каждые 3-5 минут) добавляются новости. За год работы таких новостей скопилось порядка 130 тысяч. Так как авторизация на новостных сайтах не нужна, то трафик преимущественно анонимный. Чтобы держать нагрузку мы включаем кэш анонимов и настраиваем минимальное время жизни кэша на 5 минут (чтобы добавленные новости были видны анонимам максимально быстро). А теперь давайте посмотрим, что же будет происходить с кэшем:

  • По истечению 5 минут рано или поздно будет добавлен новый материал. Это значит, что весь кэш страниц очистится (вспоминаем про сброс временного кэша).
  • Не забываем, что за год работы наш проект изрядно полюбился поисковым системам, и каждую секунду мы стабильно получаем хит от какого-либо бота. Причём эти хиты могут идти как на старые, так и на новые страницы. Директива Crawl-delay в роботсах успешно игнорируется многими ботами, включая яндекс и гугл. Проверено на собственных проектах.
  • Так как наш ресурс для людей, которых десятки и сотни тысяч в сутки, то и они существенно прибавляют нагрузки на сервер. Ведь шанс того, что за 5 минут два и более пользователей зашли на одну страницу достаточно невелик (а мы помним, что страниц у нас больше ста тысяч). А в этом случае вся эффективность от кэша страниц вообще стремится к нулю.

И вот теперь, зная, что вы владеете знаниями о работе кэша страниц, я готов рассказать о своём новом модуле.

Memcache Storage Page Cache

Надеюсь вы помните о том, что отдавать HTML страницы анонимам можно без обращения к базе данных за каких-то 20-30 милисекунд (если не помните - вспоминайте). Это, конечно, мощно. Однако зная, что по истечению времени жизни кэша отдавать будет уже нечего (а на больших сайтах это минут 5-10), становится несколько печально. Поэтому сам собой напрашивается вопрос - а почему бы нам не сбрасывать кэш только для тех страниц, которые были обновлены? Именно для этого и был разработан модуль Memcache Storage Page Cache. Он позволяет выбирать действия, после которых будет сброшен кэш для определённых страниц. Для остальных же страниц кэш будет жить вечно (ну или по крайней мере до тех пор, пока он оттуда по другим причинам не будет выдворен).

И вот теперь вы сможете прочуствовать всю силу кэша страниц! У вас 100 тысяч материалов на сайте, и вы добавили ещё один? Отлично! Давайте сразу же покажем анониму этот материал, но остальные страницы мы трогать не будем. Добавился комментарий? Супер! Давайте обновим страницу, где находится комментарий, а остальные оставим оставим мирно лежать в кэше.

Таким образом, на страницы сайта может заходить эпически большое количество посетителей и ботов, а ваш сервер будет отдавать страницы с такой скоростью, как будто в бэкенде у него никакого Друпала нет и в помине. Причём этот эффект не прекратится, даже если был изменён контент на сайте. Лёгкое замедление почуствует лишь первый аноним, посетивший обновлённую страницу.

В результате нагрузка на сервер снижается в десятки раз. Безусловно, здесь надо учитывать специфику сайта. Если сайт представляет из себя социальную сеть наподобие vk или facebook, куда анонимам вообще дорога заказана, то там этот модуль будет бесполезен. Однако на подавляющем большестве сайтов анонимный трафик существенно превыщает количество авторизованных пользователей. А это значит, что применение ему вы точно найдёте ;)

Конфигурация Memcache Storage

Для того, чтобы воспользоваться моим решением, ваш settings.php должен содержать как минимум такие настройки:

# Memcache Storage integration.
$conf['cache_backends'][] = 'sites/all/modules/memcache_storage/memcache_storage.inc';
$conf['cache_default_class'] = 'MemcacheStorage';
$conf['cache_class_cache_form'] = 'DrupalDatabaseCache';
 
# Configure page cache expiration.
$conf['memcache_storage_page_cache_custom_expiration'] = TRUE;
$conf['memcache_storage_page_cache_expire'] = 0;  // NEVER EXPIRE.
 
# Avoid database connection for cached pages.
$conf['page_cache_without_database'] = TRUE;
$conf['page_cache_invoke_hooks'] = FALSE;

Если всё же боитесь, что для каких-то страниц кэш не будет сброшен, то периодически их обновлять надо, вы можете задать сброс кэша на каждые, скажем, 3 дня:

# Configure page cache expiration.
$conf['memcache_storage_page_cache_custom_expiration'] = TRUE;
$conf['memcache_storage_page_cache_expire'] = 60 * 60 * 24 * 3; // 3 days.

Более подробно о настройках вы можете прочитать в README модуля Memcache Storage, или же в статье об этом модуле.

Настройки Memcache Storage Page Cache

На странице /admin/config/development/memcache_storage/page_cache вы найдёте страницу с настройками модуля. Первая часть с настройками выглядит так:

page_cache_2.png

Эти настройки позволяют выбрать действия, после которых будет вызываться очистка кэша. Например, вы можете указать, чтобы кэш страниц сбрасывался только после добавления или удаления комментария, а при обновлении ничего не должно сбрасываться вообще.

Вторая часть выглядит следующим образом:

page_cache_3_0.png

Она определяет, для каких страниц кэш должен быть очищен. Модуль умеет чистить следующие страницы:

  • Главную страницу
  • Страницу с сущностью, для которой выполняется действие
  • Страницы с терминами таксономии, к которым относится материал
  • Страницы со связанными материалами, которые были связаны с помощью модуля Node reference (из набора References)
  • Любые другие страницы, заданные пользователем. Для таких страниц поддерживаются токены. При нажатии на ссылку View available tokens показывается попап с доступными токенами для вставки в текущее поле. Токены не отображаются сразу под полем, чтобы не загружать всю пачку с токенами при загрузке страницы (на больших сайтах это реальная проблема). Более того, пользовательские страницы поддерживают сброс по wildcard. Достаточно к урлу дописать |wildcard, и кэш сбросится для всех урлов, начинающихся с указанного текста.

Если вы захотите для какого-либо типа материала настроить свои правила для сброса кэша - на странице с настройкой типа материала вы найдёте такую вкладку:

page_cache_4_0.png

Настройки те же, что и на странице с глобальными настройками.

Пользуйтесь на здоровье!

P.S. Если кто-то найдёт время, чтобы перевести настройки на русский - буду очень признателен, ибо времени не хватает катастрофически.

Обновлено 26.06.2013

Memcache Storage Page Cache полностью переехал в Cache Expiration, и убран из Memcache Storage. Все настройки (и даже больше) теперь находятся в Cache Expiration 7.x-2.x.

Комментарии

Аватар пользователя user1
user1 написал:

а для авторизованных юзеров какой модуль используете?

13.04.2013 22:33
Аватар пользователя Spleshka
Spleshka написал:

Самый простой ответ - Authcache. Однако на самом деле тут всё гораздо сложнее. Для авторизованных пользователей обычно используется мозг :) Производительность загрузки страницы для авторизованных зависит от большого количества мелких кусков, из которых собирается эта страница. И я минимизурую время загрузки каждого из этих кусков путём настройки кэширования, отладки запросов, поиска утечки памяти и так далее. Универсального ответа на ваш вопрос не существует.

13.04.2013 22:44
Аватар пользователя andypost@drupal.org
andypost@drupal.org написал:

Также важно учитывать, что если у вас на всех страницах выводится блок "последние материалы" то придется сбрасывать кеш всех страниц (именно поэтому стандартное поведение чистит всё). Альтернативой является использование http://dgo.to/esi и подобных технологий - те сборка страницы всё же нужна, но собирается они из частей с разным временем жизни

13.04.2013 22:50
Аватар пользователя Spleshka
Spleshka написал:

Спасибо Андрей, ценное дополнение, как и всегда :)

14.04.2013 00:02
Аватар пользователя user1
user1 написал:

а можно как то добиться чтобы этот кэш к примеру днём сбрасывался при обновлении(редактировании,добавлении) нод или комментов , а допустим ночью он очищался просто по минимальному времени кеша.
То есть как привязать кеш к времени сервера?

14.04.2013 17:00
Аватар пользователя Spleshka
Spleshka написал:

Именно как вы хотите - функционала нет. Но можно поставить время жизни кэша страниц на 12 часов например. И получится так, что днём он будет очищаться после каких-либо действий, а ночью он может сброситься сам, по истечению срока годности.

14.04.2013 17:31
Аватар пользователя user1
user1 написал:

но здесь все же будет относительное время (длительность , duration) ,кеш то можно и принудительно сбросить
и тогда как я понимаю все сдвинеться

14.04.2013 18:21
Аватар пользователя Spleshka
Spleshka написал:

Да, конечно. Я же и говорю - такого механизма работы кэша по времени суток не предусмотрено. Более того, я не считаю этот механизм чем-то действительно нужным, т.к. пользы от него я не вижу.

14.04.2013 19:26
Аватар пользователя xandeadx
xandeadx написал:

я как-то пытался решить похожий вопрос — http://xandeadx.ru/blog/drupal/396

12.05.2013 05:10
Аватар пользователя Astral
Astral написал:

А если сайт продаёт ссылки, типа Sape, и на десятка страниц ежедневно продаются новые ссылки (ссылки располагаются в блоках, но в кэш попадает страница вместе с нодой и со всеми блоками...).
1. Можно ли как то сделать так, чтобы именно эти страницы обновились (сбросился кеш), а другие не трогать?
2. Можно ли как то сделать так, чтобы кеш не просто удалялся, а заного попадал туда но уже обновлённый, не дожидаясь посещения сайта посетителем?

13.06.2013 16:10
Аватар пользователя Spleshka
Spleshka написал:

1. Да. Смотрите в сторону модулей Memcache Storage Page Cache (в составе Memcache Storage), или Cache Expiration. Там вы можете задать кастомные правила для сброса кэша.

2. Да. Обратите внимание на модуль Cache warmer.

13.06.2013 20:43
Аватар пользователя Astral
Astral написал:

Подскажите, пришла идея снизить нагрузку на сайт, зарегистрировав доп. аккаунт Виртуального хостинга у хостера, в связи с чем вопрос, какая комбинация настроек может дать лучший результат в производительности?

Сейчас:
Аккаунт #1. (10 gb HDD, 1 гб ОЗУ, 600 МHZ, 1 msql), используется для Memcache = 384 мб, остальное на работу с базой данных.

Варианты:
1. Перестать использовать memcache на аккаунте №1, высвободив таким образом 384 мб ОЗУ и запустить на аккаунте #2 memcache с ОЗУ на 900 мб, соответственно изменив настройки в settings.php для memcache. (данный вариант кажется самым простым в реализации, однако прирост даст видимо незначительный = 384 мб ОЗУ, ведь кеш страниц сейчас обновляется каждый час).

2. Использовать на аккаунте №2 базу данных для таблицы cache_form, так как она самая нагруженная и к ней в основном идут обращения, чтобы что-то взять из кеша помимо memcache. Таким образом будут использоваться 2 базы данных, что по идее должно снизить нагрузку на базу/процессор и выдавать информацию быстрее. Подскажите какие ещё таблицы сюда лучше включить.

3. Видимо чтобы получить максимальный эффект в производительности за счёт параллельности процессов, нужно на обоих аккаунтах использовать memcache (на каждом в memcache будет попадать что-то конкретное, подскажите что именно прописать в один и другой и какие размеры пула сделать). И тоже самое с базами данных, использовать обе (какие таблицы оставить на аккаунте №1, а какие использовать на аккаунте №2?).

Может быть есть и другие варианты, как лучше всё организовать?

18.06.2013 02:46
Аватар пользователя Astral
Astral написал:

Подскажите, периодически, 2 раза было за месяц, слетает процесс memcached и на всех страницах сайта для всеобщего обозрения красным цветом - надпись о том, что к серверу memcached невозможно подключиться.

С одной стороны, можно убрать для показа этот блок, но как я понимаю этот же блок используется и для сообщений типа "ваше письмо отправлено", "неправильно введена капча" и т.д.

Есть ли какие-то идеи по какой причине может слетать процесс и как не показывать это сообщение всем при слёте процесса?

20.06.2013 15:59
Аватар пользователя Spleshka
Spleshka написал:

Почему слетает процесс не подскажу, т.к. проблема не распространённая и находится непосредственно на сервере.
Как не показывать ошибки - зайдите по адресу /admin/config/development/logging и отключите отображение сообщений об ошибках.

21.06.2013 14:21
Аватар пользователя Astral
Astral написал:

По указанному адресу и так выбрано "Нет", тут дел в другом, как я понимаю это блок "Системная справка".

Если отключить этот блок, то тогда не будут выводится ошибки пользователям, например при отправке формы, типа "неверное введён е-мейл" или "неверно заполнена капча" и т.д.

Но, хостер откликнулся, и написал скрипт, который проверяет memcache на запуск и если не запущен, запускает его командой, поставил по крону каждые полчаса....

Вопрос, запуск такого крона через cpanel хостера - будет запсукать только данный скрипт (команду) или всё что запускается по крону в drupal тоже (обновления, переводы и т.д.)?

21.06.2013 21:42
Аватар пользователя Astral
Astral написал:

Есть представление которое делает список из всех материалов сайта (заголовок + 200 знаков из body), с разбивкой по 500 на странице, в итоге 10 страниц (это типа html карта сайта).

Проблема в том, что если без кеша, то пауки сканируя разом эти 10 страниц вешают сайт, если включить во views кеширование, то страница перестаёт грузится с сообщением, что memcache не хватает памяти для её показа, типа взято 163 мб и не хватает ещё около 63 мб...(и это только для генерации 1 страницы, кстати без кеша представления первый раз страница грузится около 25 секунд, повторно благодаря memcache уже 254 ms).

Что лучше сделать с такой ситуацией?

Думаю нужно чтобы такие страницы лежали в кеше базы данных и брались оттуда и не сбрасывались при автоматическом сбросе страниц memcache (стоит каждые 3 часа в настройках) или кеше Drupal (каждые 6 часов). Как это реализовать лучше?

22.06.2013 03:20
Аватар пользователя Spleshka
Spleshka написал:

Здесь надо оптимизировать страницы. Memcached лишь позволяет снизить нагрузку на сервер, но не поможет решить ситуацию с 25секундами. Прочтите и попробуйте на практике эту статью.

22.06.2013 16:11
Аватар пользователя AmiGator
AmiGator написал:

Случайно наткнулся на д.орге на модулёк Alternative Database Cache https://drupal.org/project/adbc
не могу понять, фигня или где то его можно использовать с пользой?

10.04.2014 16:55

Комментировать