2012-12-07 9 views
6

Po prostu zaczynam rozumieć pamięć podręczną jako całość. Mam proste indexAction(), które pobiera wszystkie dane zestawów danych. Moje podejście jest:Jak podejść do buforowania w ZF2

  • czek na istniejący klucz „controllername-Index-index”
  • jeśli istniejący: zwraca wartość klucz
  • jeśli nie istniejących, zrobić normalne działanie i dodać klucz

Wartość wewnątrz klucza powinna być ViewModel, który zostanie wygenerowany i wypełniony moimi danymi.

Oto co zrobiłem do tej pory:

<?php 
public function indexAction() 
{ 
    $sl = $this->getServiceLocator(); 
// $cache = $sl->get('cache'); 
// $key = 'kennzahlen-index-index'; 
// 
// if ($cache->hasItem($key)) { 
//  return $cache->getItem($key); 
// } 

    $viewModel = new ViewModel(); 
    $viewModel->setTemplate('kennzahlen/index/index'); 
    $entityService = $sl->get('kennzahlen_referenzwert_service'); 
    $viewModel->setVariable('entities', $entityService->findAll()); 

// $cache->setItem($key, $viewModel); 

    return $viewModel; 
} 

Części buforowania są komentarzem do celów testowych, ale w zasadzie jest to wszystko, co robię. Konfiguracja/usługa buforowania wygląda następująco:

<?php 
'cache' => function() { 
    return \Zend\Cache\StorageFactory::factory(array(
     'adapter' => array(
      'name' => 'filesystem', 
      'options' => array(
       'cache_dir' => __DIR__ . '/../../data/cache', 
       'ttl' => 100 
      ), 
     ), 
     'plugins' => array(
      array(
       'name' => 'serializer', 
       'options' => array(

       ) 
      ) 
     ) 
    )); 
}, 

Serializacja i buforowanie działają całkiem nieźle, ale jestem zaskoczony brakującymi wynikami. Przechodząc przez to, co mówi mi ZendDevelopersToolbar, czasy BEZ buforowania sięgają od 1.8s do 2.5s. Brak części komentarza (włączone) w rzeczywistości nie poprawia w ogóle czasu ładowania mojej strony.

Moje pytanie brzmi: czy to podejście jest całkowicie błędne? Czy istnieją inne, szybsze części, które można zaoszczędzić dzięki pewnym sztuczkom konfiguracyjnym?

Uważam, że 2-sekundowy czas ładowania strony jest ZDECYDOWANIE zbyt wolny. 1s to dla mnie maksymalna ilość danych, ale z pewnością nie jest to nic więcej: S

Wszystkie pomoc/podpowiedzi/sugestie będą bardzo mile widziane. Z góry dziękuję!

+0

Czy jesteś pewien, że ta konkretna część jest przyczyną konieczności ten problem? Moje strony ZF2 zwykle działają poniżej 100 ms, więc powinna istnieć inna przyczyna tego. Również wolałbym buforować określone wyniki zapytania, bez modeli widoku. Jeśli chcesz cache cokolwiek związanego z widokiem, cache renderowania widoku, pomiń także parsowanie plików .phtml. W przeciwnym razie buforuj wynik usługi. –

+0

Pytanie, gdzie należy wstrzyknąć kod, aby umożliwić już buforowanie renderowania widoku? Chociaż najwyraźniej byłbym mądry sugerował by zobaczyć, co sprawia, że ​​mój scenariusz jest tak powolny. Naprawdę nie ma włączonych wielu modułów, zfcuser, bjyauthorize, zenddeveloperstoolbar i the doktryna-stuff + mój moduł, który używa doktryny, aby uzyskać pewne elementy db: S – Sam

+0

Odpowiedziałem na możliwą opcję pamięci podręcznej, w której twój wynik html jest buforowany. Zainstaluj Xdebug i wykonaj kilka działań profilujących, aby zobaczyć, co jest prawdziwym wąskim gardłem twojej aplikacji. –

Odpowiedz

17

Jedną opcją jest buforowanie kompletnego wyniku strony, na przykład na podstawie dopasowania trasy. Trzeba słuchać między routingiem i wysyłki, która trasa została uznana za mecz, a następnie podjąć odpowiednie działania:

namespace MyModule; 

use Zend\Mvc\MvcEvent; 

class Module 
{ 
    public function onBootstrap(MvcEvent $e) 
    { 
     // A list of routes to be cached 
     $routes = array('foo/bar', 'foo/baz'); 

     $app = $e->getApplication(); 
     $em = $app->getEventManager(); 
     $sm = $app->getServiceManager(); 

     $em->attach(MvcEvent::EVENT_ROUTE, function($e) use ($sm) { 
      $route = $e->getRouteMatch()->getMatchedRouteName(); 
      $cache = $sm->get('cache-service'); 
      $key = 'route-cache-' . $route; 

      if ($cache->hasItem($key)) { 
       // Handle response 
       $content = $cache->getItem($key); 

       $response = $e->getResponse(); 
       $response->setContent($content); 

       return $response; 
      } 
     }, -1000); // Low, then routing has happened 

     $em->attach(MvcEvent::EVENT_RENDER, function($e) use ($sm, $routes) { 
      $route = $e->getRouteMatch()->getMatchedRouteName(); 
      if (!in_array($route, $routes)) { 
       return; 
      } 

      $response = $e->getResponse(); 
      $content = $response->getContent(); 

      $cache = $sm->get('cache-service'); 
      $key = 'route-cache-' . $route; 
      $cache->setItem($key, $content); 
     }, -1000); // Late, then rendering has happened 
    } 
} 

Drugi sprawdza słuchacza w tym przypadku renderowania. Jeśli tak się stanie, wynik odpowiedzi zostanie zapisany w pamięci podręcznej.

Ten system (być może nie ze 100% kopiowaniem/wklejaniem, ale koncepcja) działa, ponieważ jeśli zwrócisz Response podczas trasy lub zdarzenia wysyłki, aplikacja spowoduje zwarcie w przepływie aplikacji i zatrzyma dalsze wyzwalanie detektorów. Wtedy ta odpowiedź będzie słuszna.

Pamiętaj, że będzie to pełna strona (łącznie z układem). Jeśli tego nie chcesz (tylko kontroler), przenieś logikę do kontrolera. Pierwsze zdarzenie (teraz trasa) będzie wysyłką kontrolera. Posłuchaj tego wcześnie, aby normalne wykonanie akcji zostało pominięte. Aby buforować wynik, sprawdź zdarzenie renderowania dla warstwy widoku, którą chcesz odsłuchać.

/aktualizacja: Napisałem mały moduł do używania tego suchego w aplikacji: SlmCache

+0

Dziękuję za te przykłady. XDebug naprawdę będzie kolejną rzeczą do zrobienia. Ten przykład jednak - dla mnie - działa jak dobre odniesienie do użycia EventManagera, co jest czymś, czego jeszcze nie do końca zrozumiałem :) Dzięki za to, będzie się liczyć w poniedziałek;) – Sam

+0

Zaakceptuję tę odpowiedź, ponieważ ma ogólny cel. Jednak moim błędem, po niektórych xdebuggingach, wydaje się być moje połączenie DB, które trwa 1s w lokalnym środowisku xampp, więc muszę to jakoś wymyślić;) Dzięki za pomoc! – Sam

+0

Myślę, że czytałem gdzieś, że zdarzenia 'pre' i' post' są bardzo przydatne do buforowania rzeczy. Pre dla sprawdzania, czy w pamięci podręcznej (następnie zwracanie, jeśli tak) i Post dla dodawania do pamięci podręcznej po wykonaniu Bootstrap/cokolwiek. –