Czy istnieje sposób na podpięcie się do czyszczenia pamięci podręcznej?


16

W przypadku witryny dużej instytucji z dużymi pamięciami podręcznymi chciałbym wygenerować pamięć podręczną tak szybko, jak to możliwe, aby żaden użytkownik nie pojawił się przy generowaniu pamięci podręcznej ...

Mam ustawiony cron na wszystkie minuty, który to robi, wykonując kilka funkcji i żądając krytycznych stron, ale to, czego szukam, to sposób, aby wiedzieć, kiedy pamięć podręczna została właśnie wyczyszczona , najlepiej hak, więc mogę ją uruchomić funkcje generujące.

Dowolny pomysł ?


W zależności od tego, co próbujesz osiągnąć, odpowiedź phayes na stronie jest dobrym rozwiązaniem do odpalenia kodu po wyczyszczeniu pamięci podręcznej.
Lester Peabody

Odpowiedzi:


7

Nie ma go w Drupal 7.x, ale został dodany jako podstawowy hak, hook_rebuild w Drupal 8.x po tym, jak o to poprosiło wystarczająca liczba osób. Może być lepszy sposób na rozwiązanie problemu w wersji 7.x - próbujesz zainicjować jakąś funkcję podgrzewania pamięci podręcznej zaraz po tym, jak cron wyczyści pamięć podręczną, prawda? Innym sposobem podejścia do tego byłoby użycie Elysia cron, który ma wiele znaczących ulepszeń w działaniu crona, ale dwa, które mogą być istotne dla twojego przypadku użycia to:

Elysia Cron rozszerza standardowy cron Drupala, umożliwiając precyzyjną kontrolę ziarna nad każdym zadaniem i kilka sposobów dodawania niestandardowych zadań cron do twojej witryny.

  • Ustaw czas i częstotliwość każdego zadania cron (możesz uruchamiać niektóre zadania codziennie o określonej godzinie, inne tylko co miesiąc itd.). Do każdego zadania możesz po prostu wybrać jedną z często używanych opcji („raz dziennie”, „raz w miesiącu” ...) lub użyć potężnej składni podobnej do „linux crontab”, aby ustawić dokładne czasy. Możesz nawet zdefiniować często używane opcje, aby przyspieszyć konfigurację witryny. ...
  • Zmień priorytet / kolejność wykonywania zadań. ...

Możesz użyć tego modułu, aby mieć lepszą kontrolę nad działaniem twojego crona, aby pomóc rozwiązać problem przestarzałej pamięci podręcznej. W szczególności możesz dodać hak do swoich funkcji przebudowy do crona, a następnie używając cronu Elysia, ustawić te operacje, aby były uruchamiane natychmiast po operacji czyszczenia pamięci podręcznej.

Wygląda również na to, że masz problemy z uruchomieniem crona, co często prowadzi do zbyt częstego odtwarzania pamięci podręcznej. W takim przypadku można ustawić określoną operację czyszczenia pamięci podręcznej w cronie Elysia, aby działała z inną częstotliwością niż pozostałe operacje cron, więc na przykład indeksowanie wyszukiwania będzie aktualizowane co 5 minut, ale pełne czyszczenie pamięci podręcznej będzie uruchamiane co 6 godzin itp.

Precyzyjne zarządzanie pamięcią podręczną crona: drupal cron unieważnia zmienną pamięć podręczną przy każdym uruchomieniu crona, a jest to wielki problem z wydajnością, jeśli masz często wywoływane zadanie. Elysia cron optymalizuje zarządzanie pamięcią podręczną i nie musi unieważniać pamięci podręcznej.


Cóż, to prawdziwy bummer. Pospiesz się D8! W rzeczywistości mam, jak już mówiłem, crona z elysia_cron, biegnącego co minutę, ogrzewającego to, czego potrzebuję. Ale ponieważ moja strona będzie miała> 10.000 / odwiedzin / godzinę, jestem prawie pewien, że sbdy spadnie na puste skrzynki ... Dzięki, wiem, że to ograniczenie D7!
Gregory Kapustin

12

Można to zrobić hook_flush_cachesw połączeniu z register_shutdown_function. Przykładowy kod:

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

Użycie register_shutdown_functionoznacza, że ​​nasza funkcja odbudowywania pamięci podręcznej zostanie wywołana po wyczyszczeniu pamięci podręcznej. Nadużywamy hook_flush_cachesw sposób, który nigdy nie był przeznaczony do użycia, ale powinno to robić dokładnie to, czego potrzebujesz.


Naprawdę podoba mi się to rozwiązanie. Przed samodzielnym użyciem szukałem znanych problemów / konfliktów register_shutdown_function()w Drupal i natknąłem się na drupal_register_shutdown_function () rdzenia Drupala : „Wrapper for register_shutdown_function (), który przechwytuje wyjątki, aby uniknąć„ wyjątku zgłoszonego bez ramki stosu w Nieznany ” . wiem, że to sprawia, że czuję się lepiej, abusing hook_flush_cachesjeśli używam do tego tylko podstawowych funkcji Drupala.
Runwithscissors

11

Nie, nie ma. Nie całkiem. Przynajmniej nie w 6 lub 7. Zakładając 7:

Jeśli na to spojrzysz drupal_flush_all_caches(), zobaczysz, że to wywołuje hook_flush_caches(). Ten hak ma na celu:

„dodaj nazwy tabel pamięci podręcznej do listy tabel pamięci podręcznej, które zostaną wyczyszczone przyciskiem Wyczyść na stronie Wydajność lub za każdym razem, gdy wywoływane są drupal_flush_all_caches.”

Byłoby kuszące, aby po prostu przechwycić moduł i napisać tam kod. Ale spójrzmy jeszcze raz drupal_flush_all_caches(). Rzeczywiste usunięcie odbywa się w następujący sposób:

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

Oznacza to, że wszystkie haki są uruchamiane, zanim cokolwiek zostanie naprawdę usunięte. Jest tylko jedna funkcja wywoływana po rzeczywistego usunięcia, _system_update_bootstrap_status()ale to tylko nazywa hook_boot, hook_exit, hook_watchdogi hook_language_init- haki nie chcesz wdrożyć tylko w celu zapewnienia funkcjonalności cache-jasne-zależnej.


Cholera, zajęło mi dużo czasu, aby dodać wszystkie te linki;) Zostawię to na razie, ponieważ nie mogę zmusić się do usunięcia, po tylu latach poświęconych na wyjaśnienie, dlaczego nie można tego zrobić.
Mołot

3
Zostaw to dobra odpowiedź.
mpdonadio

Tak, zostaw to, nie mogę sprawdzić wszystkich dobrych odpowiedzi, ale poprawiłem :)
Gregory Kapustin

8

Szerokie pociągnięcia tutaj:

Chociaż w wersji wcześniejszej niż D8 nie ma żadnych haczyków, możesz napisać własny backend bazy danych w oparciu o standardowy, DrupalDatabaseCachea następnie zapisać dowolną logikę w swojej clear()funkcji. Szybkie spojrzenie sugerowałoby, że jest to dość proste w D7 (po prostu skopiuj klasę do swojej niestandardowej nazwy i zmodyfikuj ją itp., Wrzucającmodule_invoke_all() odpowiednio) i z modułem cache_backport będzie działał nawet w D6. Następnie wskaż dowolne pojemniki pamięci podręcznej, które chcesz wyczyścić, i powinieneś być na dobrej drodze.


3
Jest to prawdopodobnie najlepsze rozwiązanie, jedynym „problemem” jest to, że jeśli masz wiele pojemników pamięci podręcznej (memcache, redis itp.), Musisz rozszerzyć kilka klas pamięci podręcznej. Nadal warto
Clive

Czy nie działałoby to z pamięcią podręczną w memcached, apc lub innym rozwiązaniu innym niż db, prawda?
Mołot

Używam Redis, nie jestem pewien, czy to zadziała.
Gregory Kapustin

Jeśli korzystasz z drupal.org/project/redis , powinieneś być w stanie po prostu skopiować lub w inny sposób zmodyfikować dostarczone klasy itp. W niestandardowym module, a następnie użyć ich zamiast tego. Jeśli jednak używasz czegoś wzdłuż platformy Panteonu, gdzie zapewniają one ciężkie podnoszenie Redis, to tak, musisz z nimi skoordynować.
Jimajamma

3

Jeśli spojrzysz na źródło dla drupal_flush_all_caches()iclear_cache_all() , zobaczysz, że żadne haki nie są wywoływane po czyszczeniu postów, co jest dość dużym błędem.

Bardzo trudno jest zagwarantować, że użytkownik nigdy nie będzie musiał czekać na zbudowanie niektórych wpisów pamięci podręcznej, dlatego staram się unikać jak największego czyszczenia pamięci podręcznej.

Jedną z metod, która naprawdę pomaga, jest zmodyfikowanie strony wydajności w celu połączenia modułu obsługi przesyłania, który po prostu usuwa pamięć podręczną skierowaną do przodu i nie dotyka menu, rejestru i podobnych pamięci podręcznych. Miałem z tym dobre wyniki, ponieważ odbudowa menu i rejestru zajmuje około połowy czasu na pełną odbudowę pamięci podręcznej.

Inną rzeczą, którą mam skrypt drush, który wykonuje drupal_http_request() na wszystkich moich adresach URL (nie tylko tych ważnych), aby wszystko było buforowane. Jak to się robi, zależy od strony. Czasami mogę po prostu EFQ opublikowanych węzłów i w ten sposób budować adresy URL. Innym razem możesz wyszukać tabele map witryn XML, aby uzyskać adres URL. Następnie nazywam to z mojego systemu cron tak często, jak potrzebuję.


1

Kilka opcji:
https://www.drupal.org/project/cache_graceful może być dokładnie tym, czego chcesz.

https://www.drupal.org/project/apdqc ma 2 haki, które odpalają wyczyszczenie pamięci podręcznej, umożliwiając zmianę wyczyszczenia drupal_alter('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);i po umożliwieniu zareagowania na wyczyszczenie module_invoke_all('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);. Spraw, aby APDQC działał poprawnie i ustaw $conf['apdqc_call_hook_on_clear'] = TRUE;w pliku settings.php, a następnie należy wywoływać przechwytywanie za każdym razem, gdy zostanie wyczyszczone buforowanie.


1

Może to nie być odpowiednie dla wszystkich i może nie być wystarczająco szybkie dla PO - ponieważ jest uruchamiane tylko przy inicjalizacji następnej strony. Pomogło mi to jednak uruchomić kod zaraz po „wyczyszczeniu pamięci podręcznej”, który nie był wrażliwy na czas.

Oczywiście HOOKnależy zastąpić własną nazwą modułu.

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

Jeśli masz konkretny pojemnik, na który chcesz kierować, powyższe elementy można zmodyfikować, aby je obsługiwać, o ile cały pojemnik zostanie opróżniony w miejscu wyczyszczenia pamięci podręcznej.

hook_initjest wykonywany tylko dla stron niebuforowanych. Chociaż pełne wyczyszczenie pamięci podręcznej nie powinno oznaczać braku stron w pamięci podręcznej, nie powinno to powodować problemów. Jednak zewnętrzne systemy buforowania, takie jak Varnish, staną na przeszkodzie temu wyzwalaniu i będą oznaczały, że pojawią się tylko wtedy, gdy następne prawidłowe żądanie dotrze do Drupala.

Należy również zauważyć, że w zależności od systemu buforowania - od momentu, w którym cache_setstaje się dostępny dla wszystkich współbieżnych użytkowników - ten hak może być uruchamiany wiele razy jednocześnie, szczególnie w przypadku dużej liczby użytkowników.


0

Miałem podobną potrzebę, gdy klient chciał opróżnić zarówno skrzynki Drupal, jak i Lakier, kiedy nacisnęły przycisk „opróżnij wszystkie skrzynki”. W tym celu porwałem ten element menu.

Nie trafi to w żadne wyczyszczenie pamięci podręcznej na cronie ani nigdzie indziej - tylko w linku menu.

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

Dzięki Travis, ale szukam sposobu, który podpiera każde wyraźne buforowanie, nie tylko ten, który jest uruchamiany dobrowolnie przez użytkownika.
Gregory Kapustin

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.