Optymalizacja stron internetowych opartych na Kohanie pod kątem szybkości i skalowalności

Strona, którą zbudowałem z Kohaną, została wczoraj uderzona ogromnym ruchem, co spowodowało, że zrobiłem krok wstecz i oceniłem część projektu. Jestem ciekaw jakie są jakieś standardowe techniki optymalizacji aplikacji opartych na Kohanie?

Interesuję się również benchmarkingiem. Czy muszę skonfigurować Benchmark::start() i Benchmark::stop() dla każdej metody kontrolera, aby zobaczyć czasy wykonania dla wszystkich stron, Czy mogę zastosować benchmarking globalnie i szybko?

Będę używał Cache-library więcej czasu na przyszłość, ale jestem otwarty na więcej sugestii, ponieważ jestem pewien, że jest wiele, co mogę zrobić, że po prostu nie jestem świadomy w tej chwili.

Author: Sampson, 2009-08-11

6 answers

To, co powiem w tej odpowiedzi, nie jest specyficzne dla Kohany i prawdopodobnie może dotyczyć wielu projektów PHP.

Oto kilka punktów, które przychodzą mi do głowy, gdy mówię o wydajności, skalowalności, PHP, ...
wykorzystałem wiele z tych pomysłów podczas pracy nad kilkoma projektami - i pomogły; więc prawdopodobnie mogą pomóc również tutaj.


Przede wszystkim, jeśli chodzi o spektakle, istnieje wiele aspektów/pytań, które są do rozważmy :

  • konfiguracja serwera (zarówno Apache, PHP, MySQL, inne możliwe demony, jak i system) ; możesz uzyskać więcej pomocy na ten temat na ServerFault, chyba,
  • kod PHP,
  • zapytania do bazy danych,
  • używasz czy nie Twojego serwera?
  • czy możesz użyć dowolnego mechanizmu buforowania? A może potrzebujesz zawsze więcej niż aktualnych danych na stronie?


Używanie odwrotnej proxy

Pierwszą rzeczą, która może być naprawdę przydatna, jest użycie odwrotnego proxy , Jak lakier, przed serwerem: pozwól mu buforować tyle rzeczy, ile to możliwe, więc tylko żądania, które naprawdę wymagają obliczeń PHP / MySQL (i, oczywiście, niektóre inne żądania, gdy nie znajdują się w pamięci podręcznej proxy) trafią do Apache/PHP/MySQL.

  • Po pierwsze, twój CSS / Javascript / Images -- cóż, wszystko, co jest statyczne -- prawdopodobnie nie musi być zawsze obsługiwany przez Apache
    • więc możesz mieć pamięć podręczną odwrotnego proxy.
    • serwowanie tych plików statycznych nie jest wielką sprawą dla Apache ' a, ale im mniej musi działać, tym więcej będzie w stanie zrobić z PHP.
    • pamiętaj: Apache może obsługiwać tylko ograniczoną, ograniczoną liczbę żądań na raz.
  • następnie, niech odwrotne proxy obsługują jak najwięcej stron PHP z pamięci podręcznej: prawdopodobnie są niektóre strony, które nie zmieniają się tak często i mogą być serwowane z pamięci podręcznej. Zamiast używać pamięci podręcznej opartej na PHP, dlaczego nie pozwolić innemu, lżejszemu serwerowi obsługiwać tych (i pobierać je od czasu do czasu z serwera PHP, aby były zawsze prawie aktualne)?
    • na przykład, jeśli masz jakieś kanały RSS (zazwyczaj zapominamy o nich, próbując zoptymalizować wydajność) , które są wymagane bardzo często , mając je w pamięci podręcznej przez kilka minut może zapisać setki / tysiące żądań do Apache+PHP + MySQL!
    • to samo dla najczęściej odwiedzanych stron witryny, jeśli nie zmieniają się przez co najmniej kilka minut (przykład: Strona główna?) , nie ma więc potrzeby marnowania procesora Na ponowne generowanie ich za każdym razem, gdy użytkownik je zażąda.
  • może istnieje różnica między stronami podanymi dla anonimowych użytkowników (ta sama strona dla wszystkich anonimowych użytkowników) A stronami podanymi dla zidentyfikowanych użytkowników ("Witaj Panie x, masz nowe wiadomości", na przykład) ?
      Jeśli tak, można prawdopodobnie skonfigurować odwrotne proxy do buforowania strony, która jest obsługiwana dla anonimowych użytkowników (na podstawie pliku cookie, jak zwykle cookie sesji)
  • oznacza to, że Apache + PHP ma mniej do czynienia z: tylko zidentyfikowani użytkownicy - który może być tylko niewielką częścią użytkowników.

O używaniu odwrotnego proxy jako pamięci podręcznej , dla aplikacji PHP, możesz na przykład spojrzeć na wyniki testów porównawczych pokazują 400% -700% wzrost możliwości serwera z APC i Squid Cache.
(tak, używają Squid, a ja mówiłem o varnish -- to tylko kolejna możliwość ^^ Varnish jest nowszy, ale bardziej dedykowany do buforowania)

Jeśli zrobisz to wystarczająco dobrze i uda Ci się przestać ponownie generować zbyt wiele stron, może nawet nie będziesz musiał optymalizować żadnego kodu ;-)
przynajmniej, może nie w żadnym pośpiechu... I zawsze lepiej jest wykonywać optymalizacje, gdy nie jesteś pod zbyt dużym ciśnieniem...


Na marginesie: mówisz w OP:

Strona, którą zbudowałem z Kohana została ogromny ruch wczoraj,

Jest to rodzaj nagłej sytuacji, w której odwrotne proxy może dosłownie uratować dzień , jeśli Twoja strona może poradzić sobie z nieaktualnością przez sekundę:

  • zainstaluj, skonfiguruj, pozwól always-- every normal day -- run:
    • skonfiguruj go tak, aby nie przechowywał stron PHP w pamięci podręcznej; lub tylko na krótki czas; w ten sposób zawsze wyświetlane są aktualne dane]}
  • i w dniu, w którym bierzesz efekt slashdota lub Digga:
    • Skonfiguruj odwrotne proxy, aby utrzymać strony PHP w pamięci podręcznej; lub na dłuższy okres czasu; może Twoje strony nie będą aktualne przez sekundę, ale pozwoli to twojej stronie przetrwać digg-effect!

O tym, Jak mogę wykryć i przetrwać bycie "Slashdotted"? może być ciekawa lektura.


Po stronie PHP rzeczy:

Po pierwsze: czy używasz najnowszej wersji PHP ? Są regularnie poprawiane prędkości, z nowymi wersjami ;-)
na przykład, spójrz na Benchmark gałęzi PHP od 3.0 do 5.3-CVS.

Zauważ, że występy są całkiem dobry powód do używania PHP 5.3 (zrobiłem kilka benchmarków (po francusku), a wyniki są świetne) ...
innym całkiem dobrym powodem jest oczywiście to, że PHP 5.2 osiągnął swój koniec życia i nie jest już utrzymywany!

Używasz pamięci podręcznej opcode?

  • myślę o APC-Alternative PHP Cache, na przykład (pecl, Instrukcja obsługi), które rozwiązanie widziałem używane najbardziej -- i to jest używane na wszystkich serwerach, na których pracowałem.
  • To może naprawdę obniżyć CPU-load serwera dużo, w niektórych przypadkach (widziałem CPU-load na niektórych serwerach iść z 80% do 40%, po prostu instalując APC i aktywacji to opcode-cache funkcjonalność!)
  • zasadniczo wykonanie skryptu PHP przebiega w dwóch krokach:
      W języku JAVA jest to kod źródłowy PHP, który jest odpowiednikiem kodu bajtowego Javy.]}
  • wykonanie tych opcodów
  • APC przechowuje je w pamięci, więc jest mniej pracy do wykonania za każdym razem, gdy skrypt/plik PHP jest wykonywany: pobiera tylko kody opcodes z pamięci RAM i wykonuje je.
  • być może będziesz musiał spojrzeć na APC ' s opcje konfiguracji, btw
      Jest ich sporo, a niektóre mogą mieć duży wpływ na szybkość / obciążenie procesora / łatwość użycia]}
    • na przykład wyłączenie [apc.stat](http://php.net/manual/en/apc.configuration.php#ini.apc.stat) może być dobre dla obciążenia systemu; ale oznacza to, że modyfikacje dokonane w plikach PHP nie będą brane pod uwagę, chyba że spłukasz cały bufor kodu opcode; o tym, więcej szczegółów, zobacz na przykład do stat () lub nie do stat ()?

  • Używanie pamięci podręcznej dla danych

    W miarę możliwości lepiej unikać robienia tego samego w kółko .

    Najważniejsze, o czym myślę, to oczywiście zapytania SQL: wiele twoich stron prawdopodobnie wykonuje te same zapytania, a wyniki niektórych z nich są prawdopodobnie prawie zawsze takie same... Co oznacza wiele "bezużytecznych" zapytań do bazy danych, które muszą poświęcić czas na serwowanie ciągle te same dane.
    oczywiście dotyczy to innych rzeczy, takich jak połączenia z usługami sieciowymi, pobieranie informacji z innych stron internetowych, ciężkie obliczenia, ...

    To może być bardzo interesujące dla ciebie, aby zidentyfikować:

    • które zapytania są uruchamiane wiele razy, zawsze zwracając te same dane
    • które Inne(ciężkie) obliczenia są wykonywane dużo czasu, zawsze zwracając ten sam wynik

    I przechowywać te dane/wyniki w jakimś buforze, są więc łatwiejsze do zdobycia- szybciej - i nie musisz iść do serwera SQL po "nic".

    Wielkimi mechanizmami buforowania są na przykład:

    • Oprócz opcode-cache, o którym mówiłem wcześniej, pozwala na przechowywanie danych w pamięci,
    • i / lub memcached (), co jest bardzo przydatne, jeśli dosłownie masz dużo danych i / lub używasz wielu serwerów, jako jest rozprowadzany.
    • oczywiście, można myśleć o plikach; i prawdopodobnie wiele innych pomysłów.

    Jestem prawie pewien, że Twój framework zawiera pewne rzeczy związane z pamięcią podręczną; prawdopodobnie już o tym wiesz, jak powiedziałeś "będę używał Biblioteki pamięci podręcznej więcej w przyszłości" W OP; -)


    Profilowanie

    Teraz, miłą rzeczą do zrobienia byłoby użycie Xdebug rozszerzenie do profilu Twojej aplikacji : często pozwala dość łatwo znaleźć kilka słabych punktów-przynajmniej, jeśli jest jakaś funkcja, która zajmuje dużo czasu.

    Poprawnie skonfigurowany, wygeneruje pliki profilujące, które można analizować za pomocą niektórych narzędzi graficznych, takich jak:

    • KCachegrind: Mój ulubiony, ale działa tylko na Linuksie / KDE
    • Wincachegrind Dla windows; robi nieco mniej rzeczy niż KCacheGrind, niestety -- nie wyświetla typowo callgraphs.
    • Webgrind który działa na serwerze PHP, więc działa wszędzie - ale prawdopodobnie ma mniej funkcji.

    Na przykład, oto kilka zrzutów ekranu KCacheGrind:

    KCacheGrind: główny ekran http://extern.pascal-martin.fr/so/kcachegrind/kcachegrind-1-small.png KCacheGrind : Callgraph wyeksportowany jako obraz http://extern.pascal-martin.fr/so/kcachegrind/kcachegrind-2-small.png

    (BTW, callgraph przedstawiony na drugim screenie jest zazwyczaj czymś, co ani WinCacheGrind, ani Webgrind nie mogą zrobić, o ile dobrze pamiętam^^ )


    (dzięki @Mikushi za komentarz) inna możliwość, że nie używałem zbyt wiele to xhprof rozszerzenie: pomaga również w profilowaniu, może generować callgraphs -- ale jest lżejszy niż Xdebug, który oznacza to, że powinieneś być w stanie zainstalować go na serwerze produkcyjnym.

    Powinieneś być w stanie używać go samodzielnie XHGui, które pomogą w wizualizacji danych.


    Po stronie SQL:

    Teraz, gdy rozmawialiśmy trochę o PHP, zauważ, że jest to bardziej niż możliwe, że Twoje wąskie gardło nie jest stroną PHP , ale bazą danych...

    Przynajmniej dwie lub trzy rzeczy, tutaj:

    • powinieneś określić:
      • jakie są najczęściej zadawane pytania przez Twoją aplikację
      • czy są zoptymalizowane (używając właściwych indeksów, głównie?) , używając EXPLAIN Instrukcja, jeśli używasz MySQL
      • czy można buforować niektóre z tych zapytań (Zobacz co powiedziałem wcześniej)
    • Czy Twój MySQL jest dobrze skonfigurowany? Niewiele o tym wiem, ale są pewne opcje konfiguracji, które mogą mieć pewien wpływ.

    Jednak dwie najważniejsze rzeczy są:

    • nie idź do DB, jeśli nie musisz: cache tyle, ile możesz!
    • kiedy musisz przejść do DB, użyj efektywnych zapytań: użyj indeksów; i profilu!


    I co teraz?

    Jeśli nadal czytasz, co jeszcze można zoptymalizować?

    Jest jeszcze miejsce na ulepszenia... W 2007 roku został wybrany do Izby Gmin.]}
    • Przełącz na architekturę warstwy n:
      • Włącz MySQL jest to jeden z najbardziej popularnych serwerów w Polsce.]}
      • [18]} używaj kilku serwerów PHP (i równoważenia użytkowników między nimi)
    • użyj innej maszyny do plików statycznych, z lżejszym serwerem WWW, jak:
    • użyj kilku serwerów dla MySQL, kilku serwerów dla PHP i kilku odwrotnych proxy przed te
    • oczywiście: zainstaluj demony memcached na każdym serwerze, który ma dowolną ilość wolnej pamięci RAM, i używaj ich do buforowania jak najwięcej / ma sens.
  • użyć czegoś "bardziej wydajnego", co Apache?
  • Może niektóre z tych pomysłów są trochę przesadne w twojej sytuacji ^^ / Align = "left" / .. Dlaczego nie przestudiować ich trochę, tak na wszelki wypadek ? ;-)


    A co z Kohaną?

    Twój inicjał pytanie dotyczyło optymalizacji aplikacji wykorzystującej Kohana... Cóż, zamieściłem kilka pomysłów , które są prawdziwe dla każdej aplikacji PHP ... Co oznacza, że są one prawdziwe również dla Kohana ;-)
    (nawet jeśli nie jest to specyficzne dla ^^)

    Powiedziałem: użyj pamięci podręcznej; Kohana wydaje się obsługiwać niektóre rzeczy buforowanie (sam o tym mówiłeś, więc nic nowego...)
    jeśli jest coś, co można zrobić szybko, spróbuj; -)

    Powiedziałem też, że nie powinieneś tego robić. wszystko, co nie jest konieczne; czy jest coś domyślnie włączone w Kohanie, czego nie potrzebujesz?
    przeglądając sieć, wydaje się, że jest przynajmniej coś o filtrowaniu XSS; czy tego potrzebujesz?

    Jeszcze kilka linków, które mogą się przydać:


    Wniosek?

    I podsumowując, prosta myśl:

    • ile będzie kosztować Twoja firma zapłacenie ci 5 dni? -- biorąc pod uwagę, że jest to rozsądny czas, aby zrobić kilka świetnych optymalizacji
    • ile będzie kosztować Twoja firma, aby kupić (zapłacić za?) drugi serwer i jego utrzymanie?
    • a jeśli będziesz musiał przeskalować większe?
      • ile będzie kosztować spędzenie 10 dni? więcej? optymalizujesz każdy możliwy bit swojej aplikacji?
      • a ile za Jeszcze kilka serwerów?

    Nie mówię, że nie powinieneś optymalizować: zdecydowanie powinieneś!
    aleWybierz "Szybkie" optymalizacje, które zapewnią ci duże nagrody Po Pierwsze: użycie pamięci podręcznej kodów opcode może pomóc ci uzyskać od 10 do 50 procent zniżki na obciążenie procesora serwera... A konfiguracja zajmuje tylko kilka minut; -) z drugiej strony, spędzając 3 dni za 2 proc...

    Oh, i, btw: przed zrobieniem czegokolwiek: umieścić kilka rzeczy monitorowania , więc wiesz, jakie ulepszenia zostały wprowadzone, i jak!
    bez monitorowania, nie będziesz miał pojęcia o skutkach tego, co zrobiłeś... Nawet jeśli to prawdziwa optymalizacja, czy nie!

    Na przykład, możesz użyć czegoś takiego jak RRDtool + Kaktusy.
    i pokazanie szefowi ładnej grafiki z 40% spadkiem obciążenia CPU jest zawsze świetne ;-)


    W każdym razie, i na zakończenie: miłej zabawy!
    (tak, optymalizacja to zabawa!)
    (Ergh, nie sądziłem, że tyle napiszę... Mam nadzieję, że przynajmniej niektóre części tego są przydatne... I powinienem pamiętać tę odpowiedź: może się przydać innym razem...)

     211
    Author: Pascal MARTIN,
    Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
    2017-05-23 11:54:15

    Użyj XDebug i WinCacheGrind lub WebCacheGrind do profilowania i analizy powolnego wykonywania kodu.

    WebCacheGrind http://jokke.dk/media/2008-webgrind/webgrind_small.png WinCacheGrind

     6
    Author: Alix Axel,
    Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
    2017-02-08 14:12:42

    Kod profilu z XDebug .

    Używaj dużo buforowania. Jeśli Twoje strony są względnie statyczne, najlepszym sposobem na to może być odwrotne proxy.

     5
    Author: Kornel,
    Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
    2009-08-11 12:55:32

    Kohana jest wyjmowana z pudełka bardzo szybko, z wyjątkiem użycia obiektów bazy danych. Cytując Zombor " możesz zmniejszyć zużycie pamięci, upewniając się, że używasz obiektu wyniku bazy danych zamiast tablic wyników."To sprawia ogromną różnicę w wydajności na stronie, która jest trzaskana. Nie tylko zużywa więcej pamięci, ale spowalnia wykonywanie skryptów.

    Również-musisz użyć buforowania. Wolę memcache i używam go w moich modelach w ten sposób:

    public function get($e_id)
    {
        $event_data = $this->cache->get('event_get_'.$e_id.Kohana::config('config.site_domain'));
    
        if ($event_data === NULL)
        {
            $this->db_slave
                ->select('e_id,e_name')
                ->from('Events')
                ->where('e_id', $e_id);
    
            $result = $this->db_slave->get();
            $event_data = ($result->count() ==1)? $result->current() : FALSE;
    
            $this->cache->set('event_get_'.$e_id.Kohana::config('config.site_domain'), $event_data, NULL, 300); // 5 minutes
        }
    
        return $event_data;
    }
    

    To również dramatycznie zwiększ wydajność. Powyższe dwie techniki poprawiły wydajność witryny o 80%.

    Jeśli podasz więcej informacji o tym, gdzie Twoim zdaniem jest wąskie gardło, jestem pewien, że możemy dać kilka lepszych pomysłów.

    Sprawdź również yslow (google it), aby uzyskać inne wskazówki dotyczące wydajności.

     5
    Author: ae.,
    Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
    2009-08-16 12:16:34

    Ściśle związane z Kohana (prawdopodobnie już to zrobiłeś, lub nie):

    W trybie produkcji:

    1. Włącz wewnętrzne buforowanie (spowoduje to buforowanie tylko wyników Kohana:: find_file, ale to naprawdę może bardzo pomóc.
    2. Wyłącz profiler

    Tylko moje 2 grosze:)

     1
    Author: Tamás Pap,
    Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
    2012-12-31 00:04:14

    Całkowicie się Zgadzam z Xdebug i buforowanie odpowiedzi. Nie patrz na warstwę Kohana w celu optymalizacji, dopóki nie zidentyfikujesz największych wąskich gardeł prędkości i skali.

    XDebug powie Ci, gdzie spędzasz najwięcej czasu i zidentyfikuje "hotspoty"w kodzie. Zachowaj te informacje profilujące, aby móc tworzyć podstawy i mierzyć poprawę wydajności.

    Przykładowy problem i rozwiązanie: Jeśli stwierdzisz, że za każdym razem budujesz drogie obiekty z bazy danych, to nie zmienia się często, wtedy możesz spojrzeć na buforowanie ich za pomocą memcached lub innego mechanizmu. Wszystkie te poprawki wydajności wymagają czasu i zwiększają złożoność systemu, więc upewnij się, że masz wąskie gardła, zanim zaczniesz je naprawiać.

     0
    Author: Ozten,
    Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
    2009-08-11 23:52:55