Есть ли способ зацепить очистку кэша?

16

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

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

Любая идея ?

Григорий Капустин
источник
В зависимости от того, что вы пытаетесь выполнить, ответ phayes вниз по странице является хорошим решением для запуска кода после очистки кэшей.
Лестер Пибоди

Ответы:

7

В Drupal 7.x его нет, но он был добавлен в качестве основного обработчика hook_rebuild в Drupal 8.x после того, как достаточно людей запросили его. Может быть, есть лучший способ решить вашу проблему в 7.x - вы пытаетесь запустить какую-то функцию разогрева кеша сразу после того, как cron очистит кеш, верно? Другим способом решения этой проблемы было бы использование Elysia cron, которая имеет ряд существенных улучшений в работе cron, но два, которые могут иметь отношение к вашему варианту использования:

Elysia Cron расширяет стандартный cron в Drupal, позволяя точно контролировать каждую задачу и несколько способов добавлять пользовательские задания cron на ваш сайт.

  • Установите время и частоту каждой задачи cron (некоторые задания вы можете запускать каждый день в определенный час, другие только ежемесячно и т. Д.). Для каждой задачи вы можете просто выбрать один из часто используемых параметров («один раз в день», «один раз в месяц» ...) или использовать мощный синтаксис, похожий на «linux crontab», чтобы установить точные значения времени. Вы даже можете определить часто используемые параметры для ускорения конфигурации сайта. ...
  • Изменить приоритет / порядок выполнения задачи. ...

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

Также может показаться, что у вас могут быть проблемы с запуском cron, что часто приводит к слишком частому воссозданию кэша. В этом случае вы можете настроить конкретную операцию очистки кэша в Elysia cron на частоту, отличную от остальной части ваших операций cron, поэтому, например, индексирование поиска будет обновляться каждые 5 минут, но полная очистка кэша будет выполняться только каждые 6 часов и т. Д.

Тонкая настройка управления кэшем cron: drupal cron будет аннулировать переменный кеш при каждом запуске cron, и это большая проблема с производительностью, если у вас часто вызывается задача. Elysia cron оптимизирует управление кэшем и не требует аннулирования кэша.

schnippy
источник
Ну, это настоящий облом. Спешите D8! На самом деле, у меня уже есть, как я уже говорил, cron с elysia_cron, работающий каждую минуту и ​​греющий то, что мне нужно. Но так как мой сайт будет иметь> 10.000 / посещений / час, я почти уверен, что sbdy упадет на пустые кеши ... Спасибо, так или иначе, теперь я знаю, что это ограничение D7!
Григорий Капустин
12

Способ сделать это - использовать hook_flush_cachesв сочетании с register_shutdown_function. Пример кода:

/**
 * Implements hook_flush_caches().
 */
function mymodule_flush_caches() {
   // After caches are cleared we will run mymodule_cache_rebuild()
   register_shutdown_function('mymodule_cache_rebuild');

   // We don't want to add any custom cache-tables, so just return an empty array
   return array();
}

/**
 * Rebuild expensive cache items that need to be rebuilt immediately.
 */
function mymodule_cache_rebuild() {
  // Do the cache rebuild work here
}

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

phayes
источник
Мне очень нравится это решение. Перед использованием его сам, я искал любые известные проблемы / конфликты с использованием register_shutdown_function()в Drupal, и наткнулся на Drupal сердечника drupal_register_shutdown_function () : «Wrapper для register_shutdown_function () , что уловы выброшены исключением , чтобы избежать„Exception брошенного без фрейма стека в Unknown“ . I Я знаю, это заставляет меня чувствовать себя лучше, abusing hook_flush_cachesесли я использую только основные функции Drupal для этого
runswithscissors
11

Нет, нет На самом деле, нет. По крайней мере, не в 6 или 7. Предполагая 7:

Если вы посмотрите на себя, drupal_flush_all_caches()вы увидите, что это вызываетhook_flush_caches() . Этот хук предназначен для:

msgstr "добавить имена таблиц кеша в список таблиц кеша, которые будут очищены кнопкой" Очистить "на странице производительности или при каждом вызове drupal_flush_all_caches."

Было бы заманчиво просто сделать хук вашего модуля последним и написать там код. Но давайте снова посмотрим на drupal_flush_all_caches(). Фактическое удаление происходит так:

  $cache_tables = array_merge(module_invoke_all('flush_caches'), $core);
  foreach ($cache_tables as $table) {
    cache_clear_all('*', $table, TRUE);
  }

Это означает, что все крюки срабатывают до того, как что-то действительно очистится. Существует только одна функция , которая вызывается после фактического удаления, _system_update_bootstrap_status(), но это только звонки hook_boot, hook_exit, hook_watchdogи hook_language_init- перехватывает вы не хотите , чтобы реализовать только обеспечить кэш-ясно-зависимую функциональность.

МОЛОТ
источник
Черт возьми, мне потребовалось много времени, чтобы добавить все эти ссылки;) Я оставлю это сейчас, так как я не могу заставить себя удалить его, после того, как я потратил столько времени на объяснение, почему это невозможно сделать.
Молот
3
Оставь это, это хороший ответ.
mpdonadio
Да оставь это, я не могу проверить все хорошие ответы, но я поднял это :)
Григорий Капустин
8

Широкие штрихи здесь:

Хотя в pre-D8 не было ловушки, вы могли бы написать свою собственную базу данных, основанную на стандартной, DrupalDatabaseCacheа затем вписать в свою clear()функцию любую или все виды логики . Беглый взгляд показал бы, что это будет достаточно просто в D7 (просто скопируйте класс на свое собственное имя и измените его и т. Д., Добавивmodule_invoke_all() соответствующее значение), а модуль cache_backport будет работать даже в D6. Затем укажите все ячейки кеша, которые вы хотите, чтобы все было ясно, и вы должны быть в пути.

Jimajamma
источник
3
Возможно, это лучшее решение, единственная «проблема» в том, что если у вас есть несколько кеш-блоков (memcache, redis и т. Д.), Вам нужно расширить несколько классов кеша. Тем не менее стоит
Клайв
Не будет ли работать с кешем в memcached, apc или другом не-db решении?
Молот
Я использую Redis, не уверен, что будет работать.
Григорий Капустин
Если вы используете drupal.org/project/redis, вы можете просто скопировать или иным образом изменить предоставленные классы и т. Д. В пользовательском модуле, а затем использовать их. Если, однако, вы используете что-то по аналогии с платформой Pantheon, где они обеспечивают всю тяжелую работу для redis, тогда да, вам нужно будет согласовать с ними все это.
Джимаджамма
3

Если вы посмотрите на источник drupal_flush_all_caches()иclear_cache_all() , вы увидите, что никакие хуки не вызываются после очистки, что довольно неприятно.

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

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

Другое дело, что у меня есть сценарий drush, который выполняет drupal_http_request()все мои URL-адреса (не только важные), чтобы все кэшировалось. Как это сделать, зависит от сайта. Иногда я могу просто EFQ опубликованных узлов и создавать URL-адреса таким образом. В других случаях вы можете запросить таблицы XML-карты сайта, чтобы получить ваш URL. Затем я звоню из системного cron так часто, как мне нужно.

mpdonadio
источник
1

Пара вариантов:
https://www.drupal.org/project/cache_graceful может быть именно тем, что вы хотите.

https://www.drupal.org/project/apdqc имеет 2 хука, которые запускают очистку кэша, позволяя вам изменять очистку drupal_alter('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);и после того, как вы позволяете реагировать на очистку module_invoke_all('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);. Сделайте так, чтобы APDQC работал правильно и был установлен $conf['apdqc_call_hook_on_clear'] = TRUE;в вашем файле settings.php, и тогда хуки должны вызываться всякий раз, когда выполняется очистка кэша.

mikeytown2
источник
1

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

Очевидно, HOOKнуждается в замене на ваше собственное имя модуля.

/**
 * Implements hook_init().
 */
function HOOK_init(){
  // if there is no cache_not_empty defined, define it 
  // and then trigger our cache cleared code
  if ( !cache_get('HOOK_cache_not_empty') ) {
    cache_set('HOOK_cache_not_empty', TRUE);
    foreach (module_implements('cache_cleared') as $module) {
      module_invoke($module, 'cache_cleared');
    }
  }
}

/**
 * Implements hook_cache_cleared().
 */
function HOOK_cache_cleared(){
  // do what you need here, in which ever module.
}

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

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

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

Pebbl
источник
0

У меня была похожая потребность, когда клиент хотел очистить кеш Drupal и Varnish, когда нажал кнопку «очистить все кеши». Я похитил этот пункт меню, чтобы сделать это.

Это не повлияет на очистку кэша в cron или где-либо еще - только по ссылке меню.

/**
 * Implements hook_menu_alter().
 */
function mymodule_menu_alter(&$items) {
  if (isset($items['admin_menu/flush-cache'])) {
    $items['admin_menu/flush-cache']['page callback'] =
      "_mymodule_custom_flush_cache";
  }
}

/**
 * Hijacks the "flush all caches" button in menu
 */
function _mymodule_custom_flush_cache() {
  /**
   * Clear varnish, or other logic here
   */
  admin_menu_flush_cache(); //Run the normal cache clearing stuff
}
Трэвис Лиллеберг
источник
Спасибо Тревису, но я ищу способ, которым можно было бы использовать любое кеширование, а не только то, которое пользователь запускает добровольно.
Григорий Капустин
0

Вы можете попробовать https://www.drupal.org/project/recacher - он использует модуль Cache Expiration для обнаружения страниц с истекшим сроком, а затем повторно кэширует только эти страницы, используя отличный HTTPRL.

Vacilando
источник