2012-11-26 16 views
19

W przypadku nowego projektu z dużym natężeniem ruchu zastanawiamy się, jak skonstruować naszą aplikację Symfony2, aby korzystać z pamięci podręcznych i być gotowym na bardziej agresywne działania w przyszłości. Chciałbym poznać twoją opinię.Jak skonstruować aplikację Symfony2 za pomocą ESI?

Załóżmy, że użytkownik żąda strony z listą miejsc. Ta strona posiada:

- list 
    - common data (title, author, description) 
    - user data (the user likes the list + other data) 
- first 20 places 
    - common data (title, photo of each place) 
    - user data (the rates of the user for those places) 

HTML może być tak:

<html>... 
<body> 
    <header> 
    ... 
    <!-- Embed the top user menu --> 
    <esi:include src="http://example.com/profile/menu" /> 
    ... 
    </header> 

    <content> 
    ... 
    common data of the list 
    ... 
    <!-- Embed the common data of the first 20 places, the same for everyone --> 
    <esi:include src="http://example.com/lists/17/places" /> 
    ... 
    <!-- Embed the user data of the list (used in JS) --> 
    <esi:include src="http://example.com/lists/17/user" /> 
    ... 
    <!-- Embed the user data of the list of places (used in JS) --> 
    <esi:include src="http://example.com/lists/17/places/user" /> 
    ... 
    </content> 
</body>  
</html> 

HTML będą buforowane na bramie (Symfony lub lakier). Lista miejsc będzie również buforowana przez większość czasu na bramie. Żądaniami danych użytkownika będą te, które są wywoływane i nie będą buforowane (początkowo przynajmniej nie).

Pytania:

  1. Jak się czujesz o tej struktury?
  2. Jeśli użytkownik jest anonimowy, czy mogę uniknąć wprowadzania esi-includes dla danych użytkownika? Również jeśli mam plik cookie dla użytkownika anon? W jaki sposób?
  3. Czy esi-include dla menu użytkownika ma sens?
  4. A może powinniśmy zapomnieć o ESI i zawsze przechodzić przez kontroler (na przykład buforowanie renderowanego widoku wspólnych danych)?
  5. Czy należy przenieść 2 żądania ESI, które żądają, aby dane użytkownika były wywołaniami AJAX, zamiast czekać na serwerze?
  6. Czy jest to dobre podejście do skali, jeśli musimy to zrobić szybko? Co byłoby najlepsze?

wielkie dzięki!

Odpowiedz

4

Użyliśmy Varnish na jednej stronie do buforowania całych stron i używam Symfony2 od kilku lat, ale pamiętaj, że nie używałem Varnish + Symfony2 + ESI w żadnym środowisku produkcyjnym.

  1. Myślę, że podstawowy pomysł jest OK. Jeśli menu jest takie samo na wielu stronach, a lista miejsc jest taka sama na wielu stronach, uzyskujesz wspólną zawartość buforowaną przez Varnish lub odwrotną pamięć podręczną Symfony. Ponieważ Varnish zwykle przechowuje pamięć podręczną w pamięci, dostajesz szybciej treści i nie musisz wywoływać renderowania i kodu zapytania DB na każde żądanie.

    Najtrudniejszą częścią jest buforowanie żądań ESI, jeśli użytkownik jest zalogowany. Wiem, że w domyślnej konfiguracji Varnish żądania z plikami cookie nie są nigdy buforowane. Jeśli masz tendencję do przekazywania plików cookie do żądań ESI, te odpowiedzi ESI nie będą dzielone między użytkowników.

    Możesz spróbować wprowadzić pewne reguły z adresu URL, ale jeśli używasz domyślnych pomocników Symfony, generowane adresy URL to/_internal/..., więc może być trudno odróżnić publiczne i prywatne.

    Możesz również skonfigurować tak, aby zawsze ignorować pliki cookie, jeśli przekazano Cache-Control: public. Odbywa się to domyślnie w Symfony:

    if ($this->isPrivateRequest($request) && !$response->headers->hasCacheControlDirective('public')) { 
        $response->setPrivate(true); 
    } 
    

    Jak widać z kodu, jeśli masz dyrektywę public, odpowiedź nigdy nie będzie prywatne.

    Nie znalazłem sposobu, w jaki Varnish przetwarza tę dyrektywę - jak rozumiem, nie buforuje domyślnie żadnych żądań, które mają plik cookie. Więc myślę, że musisz poprawić konfigurację, aby to osiągnąć.

  2. Jeśli strona główna ma być również buforowana, nie widzę sposobu, w jaki można pominąć załączniki.

    Zakładam, że JS jest wymagany dla zarejestrowanych użytkowników (a nie robotów wyszukiwania), więc sugerowałbym, aby używać Javascript, aby odróżnić ładowanie danych użytkownika.

    Kod JavaScript może wyglądać, jeśli użytkownik ma plik cookie session-id itd. I poprosić o podanie danych tylko w tym przypadku. Dobrym pomysłem może być ustawienie innego pliku cookie, np. _loggedin, aby kod JavaScript nie uzyskał identyfikatora sesji.

    Niezalogowani użytkownicy mogą również mieć pewne dane w plikach cookie, takie jak _likedPost:1,2,132. JavaScript może pobrać ten plik cookie i dokonać pewnych poprawek HTML, nawet bez składania dodatkowego żądania.

    Podobnie jak w przypadku plików cookie: wyodrębniliśmy pliki cookie JS-only z plików cookie aplikacji. Zrobiliśmy to za pomocą jakiegoś wzorca, np. _\w dla plików cookie JS. Następnie zmieniliśmy konfigurację Varnish, aby podzielić nagłówek Cookie i usunąć te pliki cookie JS-only. Następnie, jeśli nie pozostało żadne inne ciasteczko, odpowiedź jest udostępniana wszystkim. Aplikacja (Symfony) nie otrzymuje tych plików cookie, ponieważ są one usuwane.

  3. Myślę, że tak, jeśli jest taka sama na każdej stronie.

  4. Myślę, że ESI jest dobre, ponieważ lakier może przechowywać pamięć podręczną w pamięci. Może się tak zdarzyć, że nie będzie żadnych zapytań o zawartość dysku twardego. Ponieważ pamięć podręczna kontrolera może również znajdować się w pamięci, myślę, że Varnish będzie szukał pamięci podręcznej szybciej niż framework Symfony z routingiem, kodem PHP, inicjalizacją usług itp.

  5. To zależy, ale myślę, że mogłoby być lepszym podejściem. Należy pamiętać, że pamięci podręczne na żywo różne życia. Na przykład, jeśli twoja lista miejsc jest buforowana przez 2 godziny, pod koniec tego czasu miejsca mogą się zmienić - niektóre nowe pozycje są nowe na liście, a niektóre z nich są nieobecne. Twoja lista dla użytkownika jest wciąż stara (buforowana), ale podajesz dane użytkownika o nowej liście - niektóre dane nie są potrzebne, niektóre z nich brakuje.

    To może być lepsze podejście do pobierania wczytanych miejsc przez javascript, na przykład po wyszukanie jakiegoś atrybutu HTML, takiego jak data-list-item-id, a następnie wykonanie zapytania ajaxowego dotyczącego danych o tych elementach. W takim przypadku dane użytkownika zostaną zsynchronizowane z bieżącą buforowaną listą i można wykonać 1 żądanie ajax dla obu list zamiast 2.

  6. Jeśli nie są stosowane unieważnienia pamięci podręcznej (żądania PURGE), wszystkie szesnastkowe pamięci podręczne HTTP są rzeczywiście dobre skalować. Możesz skalować aplikację na kilka serwerów i skonfigurować Varnish, aby wywoływać je losowo, według niektórych reguł lub po prostu użyć jednego z nich jako bezpiecznego. Jeśli przepustowość jest wciąż zbyt duża, zawsze możesz zmodyfikować limity czasu cache i inną konfigurację.

+0

dziękuję barius dużo, Czynimy żądań danych użytkownika w technologii AJAX, zamiast w ESI. Zgadzam się z tobą. Zobaczmy jak idzie. Kluczem i zabawą będzie unikanie używania funkcji WYPEŁNIJ. Celem jest skalowanie. – fesja

+0

Podziel się, jak to działa, po wypróbowaniu –