大きなキャッシュを備えた大きな教育機関のウェブサイトの場合、ユーザーがキャッシュ生成にアクセスできないように、できるだけ早くキャッシュを生成したい...
私はいくつかの機能を実行し、重要なページを要求することでそれを行うcronセットをすべて持っていますが、私が探しているのはキャッシュがクリアされたときを知る方法、できればフックなので、これを起動できます生成関数。
何か案が ?
大きなキャッシュを備えた大きな教育機関のウェブサイトの場合、ユーザーがキャッシュ生成にアクセスできないように、できるだけ早くキャッシュを生成したい...
私はいくつかの機能を実行し、重要なページを要求することでそれを行うcronセットをすべて持っていますが、私が探しているのはキャッシュがクリアされたときを知る方法、できればフックなので、これを起動できます生成関数。
何か案が ?
回答:
Drupal 7.xにはありませんが、十分な人々がそれを要求した後、これはDrupal 8.xのコアフックhook_rebuildとして追加されました。7.xでは問題を解決するより良い方法があるかもしれません-cronがキャッシュをクリアした直後に何らかの種類のキャッシュウォーミング機能を開始しようとしていますか?これにアプローチする別の方法は、Elysia cronを使用することです。Elysiacronは、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が実行されるたびに変数キャッシュを無効にします。これは、頻繁に呼び出されるタスクがある場合、パフォーマンス上の大きな問題です。Elysia cronはキャッシュ管理を最適化し、キャッシュを無効にする必要はありません。
いいえ、ありません。あんまり。少なくとも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);
}
これは、本当にクリアされる前にすべてのフックが起動されることを意味します。そこでは、実際の削除後に呼び出される唯一の機能がある_system_update_bootstrap_status()
が、それは唯一の呼び出しをhook_boot
、hook_exit
、hook_watchdog
とhook_language_init
-あなたはキャッシュクリアに依存する機能を提供するためにのみ実装しないフック。
これを行う方法は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
決して使用されることを意図していない方法で悪用していますが、これはまさにあなたが必要とすることをするはずです。
ここで広範なストローク:
D8より前のバージョンにはフックがありませんが、標準的なデータベースに基づいて独自のデータベースバックエンドをDrupalDatabaseCache
記述し、clear()
関数にあらゆる種類のロジックを記述できます。簡単に見てみると、これはD7ではかなり単純であることが示唆され(クラスをカスタム名にコピーし、module_invoke_all()
必要に応じてスローすることで変更するなど)、cache_backportモジュールを使用してもD6で動作します。次に、空にしたいキャッシュビンをクリアでポイントします。
とのソースを見るdrupal_flush_all_caches()
とclear_cache_all()
、クリア後にフックが呼び出されないことがわかります。これはかなりのバグです。
ユーザーがキャッシュエントリの作成を待つ必要がないことを保証することは非常に難しいため、可能な限りキャッシュの完全なクリアを避けるようにしています。
実際に役立つ方法の1つは、パフォーマンスページを変更して、フォワードキャッシュをクリアし、メニュー、レジストリ、および同様のコアキャッシュに触れない送信ハンドラーを接続することです。メニューとレジストリの再構築は、キャッシュ全体の再構築に約半分の時間を要するため、これで良い結果が得られました。
もう1つは、drupal_http_request()
すべてのURL(重要なURLだけでなく)を処理するブラシスクリプトを使用して、すべてがキャッシュされるようにすることです。これがどのように行われるかは、サイトによって異なります。時々、公開されたノードをEFQして、そのようにURLを作成することができます。また、XMLサイトマップテーブルを照会してURLを取得することもできます。その後、必要に応じてシステムcronからこれを呼び出します。
いくつかのオプション:
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ファイルに設定します。その後、キャッシュのクリアが完了するたびにフックを呼び出す必要があります。
これはすべての人に適しているわけではなく、次のページの初期化でのみトリガーされるため、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
すべての同時ユーザーがを利用できるようになるタイミングに応じて)、特に多数のユーザーがいる場合、このフックが同時に複数回トリガーされる可能性があることに注意してください。
クライアントが「すべてのキャッシュをフラッシュ」ボタンを押したときに、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
}
https://www.drupal.org/project/recacherを試してみてください。CacheExpirationモジュールを使用して期限切れのページを検出し、優れたHTTPRLを使用してそれらのページのみを再キャッシュします。