Gibt es eine Möglichkeit, das Löschen des Caches zu überwachen?


16

Für eine große Institutionswebsite mit umfangreichen Caches möchte ich so schnell wie möglich Caches generieren, damit kein Benutzer bei der Cache-Generierung ankommt.

Ich habe alle Minuten einen Cron eingerichtet, der dies erledigt, indem er einige Funktionen ausführt und kritische Seiten anfordert. Ich suche jedoch nach einer Möglichkeit, um zu wissen, wann der Cache geleert wurde , vorzugsweise nach einem Hook, damit ich diesen starten kann Erzeugungsfunktionen.

Irgendeine Idee ?


Je nachdem, was Sie erreichen möchten, ist die Antwort von phayes auf der nächsten Seite eine gute Lösung, um den Code nach dem Löschen der Caches auszulösen.
Lester Peabody

Antworten:


7

Es gibt kein Drupal 7.x, aber dieses wurde als Core-Hook hinzugefügt, hook_rebuild in Drupal 8.x, nachdem genügend Leute es angefordert hatten. Es kann jedoch eine bessere Möglichkeit geben, Ihr Problem in 7.x zu lösen - Sie versuchen, eine Art Cache-Aufwärmfunktion zu initiieren, nachdem cron den Cache geleert hat, richtig? Eine andere Möglichkeit, dies zu erreichen, besteht in der Verwendung von Elysia cron, das eine Reihe von signifikanten Verbesserungen der Funktionsweise von cron aufweist, von denen jedoch zwei für Ihren Anwendungsfall relevant sein könnten:

Elysia Cron erweitert Drupal-Standard-Cron und ermöglicht so eine genaue Kontrolle über jede Aufgabe sowie verschiedene Möglichkeiten, Ihrer Site benutzerdefinierte Cron-Jobs hinzuzufügen.

  • Legen Sie die Zeiten und Frequenzen für die einzelnen Cron-Tasks fest (Sie können einige Jobs jeden Tag zu einer bestimmten Stunde ausführen, andere nur monatlich usw.). Für jede Aufgabe können Sie einfach zwischen einigen häufig verwendeten Optionen wählen ("einmal am Tag", "einmal im Monat" ...) oder eine leistungsfähige "Linux Crontab" -ähnliche Syntax verwenden, um die genauen Timings festzulegen. Sie können sogar häufig verwendete Optionen definieren, um die Site-Konfiguration zu beschleunigen. ...
  • Ändern Sie die Priorität / Reihenfolge der Taskausführung. ...

Mit diesem Modul können Sie die Ausführung Ihres Cron genauer steuern, um das veraltete Cache-Problem zu beheben. Insbesondere können Sie Ihren Neuerstellungsfunktionen einen Hook hinzufügen, um cron zu verwenden, und diese Vorgänge dann mit Elysia cron so einstellen, dass sie unmittelbar nach dem Cache-Löschvorgang ausgeführt werden.

Es hört sich auch so an, als hätten Sie Probleme mit Cron, was dazu führt, dass der Cache zu oft neu erstellt wird. In diesem Fall können Sie festlegen, dass der bestimmte Cache-Löschvorgang in Elysia cron mit einer anderen Geschwindigkeit ausgeführt wird als die übrigen Cron-Vorgänge. So wird beispielsweise die Suchindizierung alle 5 Minuten aktualisiert, der vollständige Cache-Löschvorgang wird jedoch nur alle 5 Minuten ausgeführt 6 Stunden usw.

Feineinstellung der Cron-Cache-Verwaltung: Drupal Cron macht den Variablen-Cache bei jedem Cron-Lauf ungültig, und dies ist ein großes Leistungsproblem, wenn Sie eine häufig aufgerufene Aufgabe haben. Elysia cron optimiert die Cache-Verwaltung und muss den Cache nicht ungültig machen.


Nun, das ist ein echter Mist. Beeilen Sie sich D8! Eigentlich habe ich, wie ich dir schon sagte, einen cron mit elysia_cron, der jede Minute rennt und wärmt, was ich brauche. Aber da meine Site> 10.000 / Visits / Stunde haben wird, bin ich mir ziemlich sicher, dass sbdy auf leere Caches fallen wird ... Trotzdem weiß ich jetzt, dass es eine D7-Einschränkung ist!
Gregory Kapustin

11

Nein, das gibt es nicht. Nicht wirklich. Zumindest nicht in 6 oder 7. Angenommen, 7:

Wenn du siehst, drupal_flush_all_caches()wirst du sehen, dass sie aufruft hook_flush_caches(). Dieser Haken soll:

msgstr "Cache - Tabellennamen zur Liste der Cache - Tabellen hinzufügen, die über die Schaltfläche" Löschen "auf der Seite" Leistung "oder bei jedem Aufruf von" drupal_flush_all_caches "gelöscht werden."

Es wäre verlockend, den Hook Ihres Moduls einfach zum Letzten zu machen und dort Code zu schreiben. Aber schauen wir uns noch einmal an drupal_flush_all_caches(). Das Löschen geschieht folgendermaßen:

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

Dies bedeutet, dass alle Haken abgefeuert werden, bevor etwas wirklich gelöscht wird. Es gibt nur eine Funktion nach der eigentlichen Löschung genannt _system_update_bootstrap_status(), aber es nur Anrufe hook_boot, hook_exit, hook_watchdogund hook_language_init- Haken Sie wollen nicht nur implementieren , bieten Cache-clear abhängige Funktionalität.


Verdammt, es hat zu lange gedauert, bis ich all diese Links hinzugefügt habe;) Ich werde es vorerst verlassen, da ich mich nicht zwingen kann, es zu löschen, nachdem ich so viel Zeit damit verbracht habe, zu erklären, warum es nicht geht.
Mołot

3
Lass es, es ist eine gute Antwort.
mpdonadio

Ja, lass es, ich kann nicht alle guten Antworten überprüfen, aber ich habe es verbessert :)
Gregory Kapustin

11

Der Weg, dies zu tun, ist hook_flush_cachesin Kombination mit register_shutdown_function. Beispielcode:

/**
 * 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
}

Using register_shutdown_functionbedeutet, dass unsere Cache-Rebuilding-Funktion aufgerufen wird, nachdem die Caches gelöscht wurden. Wir missbrauchen hook_flush_cachesauf eine Weise, die niemals beabsichtigt war, aber dies sollte genau das tun, was Sie brauchen.


8

Breite Striche hier:

Während es in Pre-D8 keinen Haken gibt, können Sie Ihr eigenes Datenbank-Backend auf Basis des Standard-Backends DrupalDatabaseCacheschreiben und dann eine oder alle Arten von Logik in Ihre clear()Funktion schreiben . Ein kurzer Blick würde darauf hindeuten, dass dies in D7 einigermaßen einfach ist (kopieren Sie die Klasse einfach in Ihren benutzerdefinierten Namen und ändern Sie sie usw., indem Sie ein module_invoke_all()entsprechendes einfügen ), und mit dem cache_backport-Modul würde es sogar in D6 funktionieren. Zeigen Sie dann auf alle Cachebehälter, auf die Sie Lust haben, und machen Sie sich auf den Weg.


3
Dies ist wahrscheinlich die beste Lösung. Das einzige Problem besteht darin, dass bei mehreren Cache-Behältern (Memcache, Redis usw.) mehrere Cache-Klassen erweitert werden müssen. Trotzdem lohnt es sich
Clive

Würde es nicht mit Cache in memcached, apc oder einer anderen Nicht-DB-Lösung funktionieren?
Mołot

Ich benutze Redis, nicht sicher, ob das funktionieren würde.
Gregory Kapustin

Wenn Sie drupal.org/project/redis verwenden , sollten Sie in der Lage sein, die bereitgestellten Klassen usw. in einem benutzerdefinierten Modul zu kopieren oder anderweitig zu ändern und sie stattdessen zu verwenden. Wenn Sie jedoch etwas in Anlehnung an die Pantheon-Plattform verwenden, bei dem das Redis-Heben von Lasten übernommen wird, dann müssen Sie dies alles mit ihnen abstimmen.
Jimajamma

3

Wenn Sie an der Quelle suchen drupal_flush_all_caches()und clear_cache_all(), sehen Sie , dass keine Haken Post Clearing aufgerufen werden, was ein ziemlich Bug doofer ist.

Es ist sehr schwierig zu garantieren, dass ein Benutzer niemals auf die Erstellung einiger Cache-Einträge warten muss, daher versuche ich, vollständige Cache-Löschvorgänge so weit wie möglich zu vermeiden.

Eine wirklich hilfreiche Methode ist das Ändern der Leistungsseite, um einen Submit-Handler einzurichten, der nur die vorwärtsgerichteten Caches löscht und die Menüs, die Registrierung und ähnliche Kerncaches nicht berührt. Ich habe damit gute Ergebnisse erzielt, da die Wiederherstellung des Menüs und der Registrierung etwa die Hälfte der Zeit für eine vollständige Cache-Wiederherstellung in Anspruch nimmt.

Das andere, was ich habe, ist ein Drush-Skript, das drupal_http_request()alle meine URLs (nicht nur die wichtigen) überprüft, damit alles zwischengespeichert wird. Wie dies gemacht wird, ist von Standort zu Standort unterschiedlich. Manchmal kann ich nur die veröffentlichten Knoten mit EFQ versehen und auf diese Weise URLs erstellen. In anderen Fällen können Sie die XML-Sitemap-Tabellen abfragen, um Ihre URL abzurufen. Ich rufe dies dann von meinem System-Cron so oft auf, wie ich es brauche.


1

Einige Optionen:
https://www.drupal.org/project/cache_graceful könnte genau das sein, was Sie wollen.

https://www.drupal.org/project/apdqc verfügt über 2 Hooks, die auf ein Cache-Clear abfeuern, sodass Sie das Clear ändern drupal_alter('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);und anschließend auf das Clear reagieren können module_invoke_all('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);. Holen Sie sich APDQC richtig funktioniert und setzen Sie $conf['apdqc_call_hook_on_clear'] = TRUE;in Ihrer settings.php-Datei & dann sollten die Hooks aufgerufen werden, wenn ein Cache-Clear durchgeführt wird.


1

Dies ist möglicherweise nicht für alle geeignet und für das OP möglicherweise nicht schnell genug, da es erst bei der Initialisierung der nächsten Seite ausgelöst wird. Es hat mir jedoch geholfen, Code auszulösen, kurz nachdem ein "Cache alle leeren", der nicht zeitkritisch war.

Muss natürlich HOOKdurch Ihren eigenen Modulnamen ersetzt werden.

/**
 * 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.
}

Wenn Sie einen bestimmten Behälter als Ziel haben, kann der obige geändert werden, um dies zu unterstützen, solange der gesamte Behälter an der Stelle geleert wird, an der der Cache leer ist.

hook_initwird nur für nicht zwischengespeicherte Seiten ausgeführt. Obwohl ein vollständiges Löschen des Cache keine zwischengespeicherten Seiten bedeuten sollte, sollte dies kein Problem verursachen. Externe Caching-Systeme wie Varnish werden diese Auslösung jedoch behindern und bedeuten, dass sie nur auftreten, wenn die nächste ordnungsgemäße Anforderung an Drupal zurückgeht.

Es sollte auch beachtet werden, dass abhängig von Ihrem Caching-System - genau dann, wenn ein cache_setfür alle gleichzeitigen Benutzer verfügbar wird - dieser Hook mehrere Male gleichzeitig ausgelöst werden kann, insbesondere wenn Sie eine große Anzahl von Benutzern haben.


0

Ich hatte ein ähnliches Bedürfnis, bei dem ein Kunde sowohl Drupal- als auch Varnish-Caches leeren wollte, als er den Knopf "Alle Caches leeren" drückte. Ich habe diesen Menüpunkt gekapert, um dies zu tun.

Dies wird keine Cache-Löschvorgänge auf cron oder anderswo treffen - nur über den Menü-Link.

/**
 * 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
}

Thx Travis, aber ich suche nach einer Möglichkeit, die sich auf eindeutiges Caching stützt, nicht nur auf die, die ein Benutzer freiwillig ausgelöst hat.
Gregory Kapustin

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.