Cachowanie stron – oszczędzanie serwera :)
- Mateusz Żeromski | 2008-10-01 | Ciekawostki Optymalizacja Php
W poprzednim artykule opisałem możliwości gzipowania plików tekstowych zanim zostaną one przesłane do użytkownika. Lecz zanim strona będzie mogła zostać zgzipowana musi być wygenerowana. Aby uzyskać super wydajność tutaj również zastosować jakiś mechanizm. W zależności od potrzeb buduje się bardziej lub mniej złożone procedury cachowania wygenerowanej treści. Stosując prosty przykład pokazuję jak łatwo jest to zrobić dla swojej stronki domowej :)
Po co?
Zawsze musi istnieć jakiś powód naszych działań, w moim przypadku była to ciekawość jak łatwo można to zrobić, oraz aby mieć powód napisać o tym tutaj, jako kontynuacja artykułu dot. gzipowania treści. Praktycznie ma to zastosowanie w serwisach których wygenerowanie strony powoduje obciążenie na serwerze, tj. łączenie do bazy danych, pobieranie danych z innych źródeł itp. Zastosowanie cachowania ucina te wszystkie procesy, a strona jest raz generowana i później tylko odczytywana, w przypadku koniecznym cache jest czyszczony, aby mógł się po chwili znów wypełniać.
Jak to działa?
- Tak: wyciągnij dane z cache i wyświetl
- Nie: Wygeneruj stronę, zapisz do cache i od razu wyświetl
- Zapytanie użytkownika o stronę
- sprawdzenie czy istnieje strona w cache
Jak widać nic złożonego. Aby ograniczyć działania po stronie serwera do minimum proponuję takie rozwiązanie.
plik .htaccess
1 2 3 4 5 | RewriteEngine on RewriteCond %{REQUEST_URI} !cache.php [NC] RewriteCond %{QUERY_STRING} !NOCACHE RewriteCond %{REQUEST_FILENAME} ^(.+)\.php$ RewriteRule (.*) cache.php?page=$1 [L] |
Oznacza to: jeżeli zapytanie nie jest o plik cache.php, jeżeli w adresie nie występuje NOCACHE, i jeżeli zapytanie jest o plik php to wykonaj :)
plik cache.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <? $request = $_SERVER['REQUEST_URI']; $fileName = 'cache/'.md5($request); if(is_file($fileName))die(file_get_contents($fileName)); $contentToCache = $request.'&NOCACHE'; require('Snoopy.class.php'); $s = new Snoopy(); $s -> fetch('http://'.$_SERVER['SERVER_ADDR'].'/'.$contentToCache); file_put_contents($fileName, $s -> results); echo $s -> results; |
Tutaj pozostawię wam analizę :)
przykładowy plik do sprawdzenia: index.php
1 2 3 4 5 | <? sleep(3); for($i=0; $i<$_GET['p']; $i++){ echo md5($i).'<br>'; } |
Należy oczywiście wywoływać z parametrem ?p=[liczba], normalne wywołanie powoduje czekanie 3 sekundy na wynik, po włączeniu mojego cache, ten czas to 20ms, czyli tyle ile powinno zajmować wygenerowanie takiej strony. Tutaj sleep oznacza procesy bazodanowe itp, które nie powinny być odczuwalne przy użyciu cache.
Opis
Powyższy przykład jest bardzo prosty i sam bym go nie śmiał wykorzystać w jakimś projekcie. Jest to tylko przykład jak można wykonać cachowanie oraz przedstawia co zyskujemy dzięki temu. To czy zostanie on wykorzystany w danym serwsie/stronce to zależy jak jest zbudowany, teraz już bardzo rzadko się tworzy strony gdzie w adresie występują parametry, raczej wszystko wygląda “seo friendly” :).
Podsumowanie
Powyższy skrypt jest LAME, ale to tylko przykład jak można zrobić coś PRO :D
Tagi: gzip, html, kompresja, Optymalizacja, php
1 Paweł 2008-10-03 12:56:10
Dla prostych stron bez ramek, zamiast podpinać Snoopy do pobrania contentu można użyć:
implode(”,file(’http://’.$_SERVER['SERVER_ADDR'].’/’.$contentToCache));
pozdrawiam
2 Mateusz Żeromski 2008-10-03 18:59:31
hmm, Snoopy is good :)
Jeżeli chodzi o pobieranie danych z www zawsze używam snoopiego, on korzysta z curla, i jest pewniejszy niż “file()”, gdybyśmy odczytywali plik z serera na którym jest skrypt to oczywiscie było by file_get_contents.
Polecam Tobie uzywanie file_get_contents, a w powyższym przypadku już lepiej jest zrobić
Chociaż wogóle nie radze używać file. Kiedyś miałem przykład że ta funkcja wczytując plik zużywała znaczenie więcej pamięci niż file_get_contents a później explode(), zresztą zrobie porównanie i udowodnie :)
pzdr