Cachowanie stron – oszczędzanie serwera :)

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?

      Zapytanie użytkownika o stronę
      sprawdzenie czy istnieje strona w cache

      • Tak: wyciągnij dane z cache i wyświetl
      • Nie: Wygeneruj stronę, zapisz do cache i od razu wyświetl

    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: , , , ,

Komentarze: 2 do “Cachowanie stron – oszczędzanie serwera :)”

  1. 1 Paweł

    Dla prostych stron bez ramek, zamiast podpinać Snoopy do pobrania contentu można użyć:

    implode(”,file(’http://’.$_SERVER['SERVER_ADDR'].’/’.$contentToCache));

    pozdrawiam

  2. 2 Mateusz Żeromski

    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ć

    1
    file($url, FILE_IGNORE_NEW_LINES);

    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

Napisz komentarz