pl  |  en

Za co nie lubi Cię Twój hoster

Tworzysz aplikację, która odmieni świat. Działa super, wygląda jeszcze lepiej, najwyższy czas pokazać ją światu. Zakładasz konto hostingowe, wrzucasz swoją aplikację i czekasz na sukces. Zamiast tego po paru dniach dostajesz poważnie brzmiącego maila od swojego usługodawcy, który powołuje się na jakieś zapisy z regulaminu i grozi wypowiedzeniem umowy. Co się stało?

Aplikacje są z reguły rozwijane w przyjaznym środowisku lokalnego komputera, gdzie zawsze wszystko działa, zasoby systemowe nigdy się nie kończą, a nad głową nie stoi z batem żaden administrator. Dlatego wdrożenie w brutalnym świecie rzeczywistego produkcyjnego środowiska może się okazać niemałym szokiem. Zebraliśmy więc parę wskazówek, które — miejmy nadzieję — pozwolą uniknąć najczęstszych problemów.

Generowanie miniaturek w locie

Jeżeli Twoja aplikacja pracuje z plikami graficznymi, to prawdopodobnie generuje z nich miniaturki. Jednym z najczęstszych błędów jest tworzenie tych miniaturek na żądanie, przy każdym wyświetleniu. Zupełnie niepotrzebnie zużywa to czas procesora, bo oryginalny obraz się już nie zmieni. Dlatego miniaturki powinny być wygenerowane raz i zachowane na dysku w taki sposób, żeby mógł je wysłać sam serwer WWW, bez udziału aplikacji (np. PHP). Najprościej to zrobić podczas wysyłania obrazu przez użytkownika (lub w analogicznym momencie jeżeli obrazy pojawiają się w systemie w inny sposób). Co jeżeli przetwarzasz dużo obrazów, a same miniaturki będą potrzebne bardzo rzadko? W takiej sytuacji idealnie będzie generować miniaturki podczas pierwszego ich wyświetlenia, np. wykrywając brakujący plik i przekierowując za pomocą mod_rewrite w pliku .htaccess:

RewriteEngine On
RewriteCond !-f %{REQUEST_FILENAME}
RewriteRule ^/thumbnails/.*/([^/]*).jpg$ /thumbnail.php?img=$1 [L]

W pliku thumbnail.php wygeneruj miniaturkę i zapisz ją w odpowiednim katalogu, po czym wyserwuj ją do klienta. Zwróć uwagę na fragment „/.*/” w wyrażeniu regularnym, które oznacza, że miniaturki nie będą się znajdowały bezpośrednio w katalogu thumbnails, lecz jakimś podkatalogu. Dlaczego? Czytaj dalej!

Duża liczba plików w jednym katalogu

Wiele aplikacji tworzy podczas działania różnego rodzaju pliki. Często są to np. wspomniane powyżej miniaturki, pliki cache systemu szablonów, czasem też sesje i inne dość ulotne dane. Najprościej trzymać je wszystkie w jednym katalogu, więc z reguły tak właśnie się dzieje. Ponieważ pojawiają się one pojedynczo, łatwo można przeoczyć fakt, że po miesiącu działania aplikacji takich plików może się uzbierać kilkadziesiąt tysięcy lub nawet więcej. Jedne systemy plików radzą sobie z taką ilością plików w jednym katalogu lepiej, inne gorzej, ale zawsze odbija się to negatywnie na wydajności aplikacji. System plików XFS bardzo szybko takie katalogi czyta, ale modyfikacje w nich są dość “drogie”, a popularny Ext3 w ogóle nie pozwala na przekroczenie 32 tysięcy plików w jednym katalogu. Poradzić sobie z tym problemem można na dwa sposoby i osobiście zalecamy skorzystanie z obydwu. Po pierwsze — trzymaj pliki w podkatalogach. Np. zamiast zapisywać miniaturkę w /thumbnails/012345.jpg, zapisz ją w /thumbnails/0/01/012345.jpg. Liczbę podkatalogów na ścieżce i schemat ich nazewnictwa musisz dopasować do spodziewanej liczby plików — zalecamy nie przekraczać kilkuset plików w jednym katalogu. Powiedzmy 1024, dla równego rachunku. Po drugie — jeżeli pliki zawierają dane, które szybko tracą ważność (sesje) lub możesz bez problemów odtworzyć względnie niewielkim kosztem (miniaturki, cache), co jakiś czas usuwaj stare pliki. Większość hostingów nie zachowuje czasu ostatniego odczytu pliku, więc trzeba się posiłkować czasem modyfikacji. Nie jest on tak miarodajny jak czas dostępu, ale i tak pozwoli utrzymać liczbę plików tymczasowych w ryzach — zwłaszcza jeżeli to np. sesje. Pliki z określonego katalogu starsze niż (przykładowy) tydzień można usunąć poleceniem:

find /pelna/sciezka/do/katalogu -type f -mtime +7 -print0 | xargs -0 rm

Wystarczy dodać to polecenie do crona (w razie problemów hoster powinien pomóc) lub skorzystać z zewnętrznych serwisów oferujących namiastkę crona, takich jak http://cronjob.de/. Wywołanie raz na dobę (najlepiej w nocy) powinno wystarczyć.

Duże pliki .htaccess

Pliki .htaccess pozwalają sterować zachowaniem Apache’a w dość szerokim zakresie, jednak czasem zdarza się webmasterom popuścić wodze fantazji i stworzyć coś, z czym nawet najszybszy serwer będzie miał problem. Serwer WWW musi czytać pliki .htaccess przy każdym wywołaniu; Apache próbuje cache’ować co może, ale nie zmienia to zbyt wiele. Dlatego złym pomysłem jest trzymanie w tym pliku dużej ilości dyrektyw, np. dla potrzeb SEO:

RewriteRule ^/pierwszy-super-artykul$ /index.php?article=1
RewriteRule ^/drugi-super-artykul$ /index.php?article=2
... i tak dalej dla ponad tysiąca podstron

lub blokowanie “na piechotę” ataków DDoS na swój serwis:

Deny from X.X.X.X
Deny from Y.Y.Y.Y
... dla kilkudziesięciu tysięcy adresów IP

Adresy stron przyjazne dla odwiedzających i wyszukiwarek lepiej załatwić na poziomie aplikacji, która sprawdzi “ładny” adres w bazie danych, a jeszcze lepiej — przeprosić się z numerami podstron w adresach i zastąpić wszystkie reguły mod_rewrite jedną:

RewriteRule ^/.*,([0-9]+)$ /index.php?article=$1

Od tej pory adresy będą wyglądały już nie tak pięknie (np. /pierwszy-super-artykul,1), ale całość na pewno przyspieszy.

Ataki DDoS najlepiej po prostu zgłosić usługodawcy, on będzie wiedział, co z tym zrobić. A jeżeli jest naprawdę dobry — już to zrobił.

Brak cache’owania

Czasem jednak nawet najlepiej zoptymalizowana strona może “wyrosnąć” ze swojego konta hostingowego. Aby jednak odsunąć jak najdalej ten moment, polecamy wspomóc się cache’owaniem danych, na każdym poziomie, gdzie ma to sens. Można cache’ować kompletne strony analogicznie do miniaturek. Jeżeli jakaś część strony musi być inna dla różnych odwiedzających (rotacja banerów, informacje o zalogowanym użytkowniku), można cache’ować wypełnione fragmenty szablonów. Czasem też warto zapamiętać wyniki bardziej skomplikowanych zapytań do bazy danych. Żeby jednak całość przyniosła oczekiwany efekt, najlepiej nie zapisywać cache fragmentów i zapytań na dysku, tylko skorzystać z dedykowanego do tego celu serwera memcached. Inaczej może się okazać, że wszystkie oszczędności zostaną zjedzone przez czas dostępu do dysku.

Rozbudowane wsparcie dla cache’owania na wszystkich interesujących poziomach oferują np. gotowe frameworki dla aplikacji WWW, takie jak Ruby on Rails (dla języka Ruby) i Django (dla Pythona).

Mailingi

Mailingi same w sobie nie są złe, przynajmniej dla usługodawcy — co myślą o tym odbiorcy to już inna sprawa. Trzeba tylko pamiętać, że serwery pocztowe nie zawsze dobrze sobie radzą z dużą kolejką poczty do wysłania, a często jednak są dzielone między wielu użytkowników. Wolne działanie poczty — niezadowoleni klienci — skargi do usługodawcy — “Informujemy iż zgodnie z Regulaminem Świadczenia Usług pkt…”. Dlatego też wszelkie mailingi najlepiej wysyłać w nocy, kiedy z poczty korzysta niewielu “żywych” użytkowników. Żeby usprawnić wysyłkę, najlepiej ją podzielić na mniejsze paczki, które serwer ma szansę obsłużyć bez nadmiernych opóźnień. Dopuszczalna szybkość samej wysyłki zależy od usługodawcy, ale za kilkaset maili na minutę w nocy nikt nie powinien się szczególnie gniewać.

Bazy danych

Bazy danych są z reguły miejscem, gdzie wydajność ma szczególne znaczenie. O kilku najczęściej popełnianych błędach i niedopatrzeniach napiszemy w następnej części.

Autor: Magda Zarych, Grzegorz Nosek

  • http://www.sojda.pl/ Mateusz

    Świetny artykuł, pozdrawiam :-)

  • http://www.sojda.pl/ Mateusz

    Świetny artykuł, pozdrawiam :-)

  • http://www.createvision.pl/ Tomasz

    Bardzo dobry artykuł.

  • http://www.createvision.pl/ Tomasz

    Bardzo dobry artykuł.