web-dev-qa-db-ja.com

キャッシュのクリアをフックする方法はありますか?

キャッシュが重い大規模な教育機関のWebサイトの場合、ユーザーがキャッシュの生成に到達しないように、できるだけ早くキャッ​​シュを生成したいと思います...

私はいくつかの機能を実行し、重要なページを要求することによってそれを行うすべての分を設定したcronを持っていますが、私が探しているのはキャッシュがクリアされたときを知る方法、できればaフックなので、この生成関数を起動できます。

何か案が ?

16

Drupal 7.xにはありませんが、これはコアフックとして追加されました hook_rebuild Drupal 8.x以降7.xで問題を解決するためのより良い方法があるかもしれません-cronがキャッシュをクリアした直後に、ある種のキャッシュウォーミング機能を開始しようとしているのですか?これに取り組む別の方法は、使用する Elysia cron には、cronの動作が大幅に改善されていますが、使用例に関連する可能性があるのは次の2つです。

Elysia CronはDrupal標準cronを拡張し、各タスクを細かく制御できるようにし、カスタムcronジョブをサイトに追加するいくつかの方法を提供します。

  • 各cronタスクのタイミングと頻度を設定します(特定の時間に毎日いくつかのジョブを実行できますが、他のジョブは毎月のみ実行できます...)。タスクごとに、頻繁に使用されるオプション(「1日1回」、「1か月に1回」...)を選択するか、強力な「linux crontab」のような構文を使用して正確なタイミングを設定できます。頻繁に使用するオプションを定義して、サイト構成を高速化することもできます。 ...
  • タスクの実行の優先順位/順序を変更します。 ...

このモジュールを使用すると、古いキャッシュの問題を解決するためにcronの実行方法をより細かく制御できます。具体的には、再構築機能にフックをcronに追加してから、Elysia cronを使用して、これらの操作をキャッシュのクリア操作の直後に実行するように設定できます。

また、cronの実行に問題があり、キャッシュが頻繁に再作成される原因となっている可能性もあります。その場合は、Elysia cronの特定のキャッシュクリア操作を他のcronオペレーションとは異なるレートで実行するように設定できます。たとえば、検索インデックス作成は5分ごとに更新されますが、完全なキャッシュクリアはすべて実行されます6時間など.

Cronキャッシュ管理の微調整:drupal cronは、cronの実行ごとに変数キャッシュを無効にします。頻繁に呼び出されるタスクがある場合、これは大きなパフォーマンスの問題です。Elysiacronはキャッシュ管理を最適化しますが、キャッシュを無効にする必要があります。

7
schnippy

これを行う方法は、hook_flush_cachesregister_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を使用すると、キャッシュ再構築関数が呼び出されますafterキャッシュがクリアされました。 hook_flush_cachesは、使用することを意図していない方法で悪用されていますが、これはあなたが必要としていることを正確に実行するはずです。

12
phayes

いいえ、ありません。あんまり。少なくとも6または7ではありません。7を想定すると、

drupal_flush_all_caches() を見ると、それが hook_flush_caches() を呼び出すことがわかります。このフックの目的は次のとおりです。

「キャッシュテーブル名を、[パフォーマンス]ページの[クリア]ボタンによって、または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);
  }
_

つまり、すべてのフックがbeforeの前に発生し、実際にすべてがクリアされます。実際の削除後に呼び出される関数は _system_update_bootstrap_status() のみですが、 _hook_boot_ を呼び出すだけです _hook_exit__hook_watchdog_ および _hook_language_init_ -実装したくないフックは、キャッシュクリア依存の機能を提供するためだけに使用します。

11
Mołot

ここで幅広いストローク:

D8より前のバージョンにはフックはありませんが、標準のDrupalDatabaseCacheに基づいて独自のデータベースバックエンドを作成し、任意のまたはすべての種類のロジックをclear()に書き込むことができます関数。簡単に見ると、これはD7でかなり簡単であることが示唆されます(クラスをカスタム名にコピーし、module_invoke_all()を適宜スローして変更するなど)および cache_backportモジュール D6でも機能します。次に、空想的にしたいキャッシュビンを明確に指定します。

8
Jimajamma

drupal_flush_all_caches() および clear_cache_all() のソースを見ると、クリア後にフックが呼び出されていないことがわかります。かなりバグが多い。

ユーザーが一部のキャッシュエントリが作成されるのを待つ必要がないことを保証することは非常に難しいため、キャッシュが完全にクリアされるのをできるだけ避けるようにします。

実際に役立つ方法の1つは、パフォーマンスページを変更して、前向きのキャッシュをクリアし、メニュー、レジストリ、および同様のコアキャッシュに触れない送信ハンドラを接続することです。メニューとレジストリの再構築には、完全なキャッシュの再構築にかかる時間の約半分がかかるため、これで良い結果が得られました。

他にも、重要なものだけでなく、すべてのURLに対して drupal_http_request() を実行するDrushスクリプトがあるため、すべてがキャッシュされます。これがどのように行われるかはサイトによって異なります。ときどき、公開されたノードをEFQし、その方法でURLを構築することができます。また、XMLサイトマップテーブルをクエリしてURLを取得することもできます。次に、必要に応じて、これをシステムcronから頻繁に呼び出します。

3
mpdonadio

いくつかのオプション:
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が正しく動作するように設定し、settings.phpファイルに$conf['apdqc_call_hook_on_clear'] = TRUE;を設定します。これにより、キャッシュのクリアが行われるたびにフックが呼び出されます。

1
mikeytown2

これはすべての人に適しているとは限りません。また、次のページの初期化時にのみトリガーされるため、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に戻ったときにのみ発生します。

キャッシュシステムによっては、cache_setは、すべての同時ユーザーが利用できるようになります。このフックは、特にユーザー数が多い場合、同時に複数回トリガーされる可能性があります。

1
Pebbl

https://www.drupal.org/project/recacher を試してみるとよいでしょう。キャッシュの有効期限モジュールを使用して期限切れのページを検出し、優れたHTTPRLを使用してそれらのページのみを再キャッシュします。

0
Vacilando

同様のニーズがあり、クライアントが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