W notce tej chciałbym przedstawić pokrótce całkiem użyteczny moduł Apache, a mianowicie mod_deflate. Dlaczego warto z niego korzystać i w jaki sposób to robić? Kiedy warto odstąpić na rzecz innych, bardziej uniwersalnych rozwiązań?
W notce tej znajdziesz krótki zbiór informacji o sposobie, w jaki ja wykorzystuję ten moduł.
Kompresja jest zdecydowanie najbardziej powszechną metodą kodowania zawartości stron internetowych. Ustawienie właściwych nagłówków kodowania dla skompresowanych treści jest niezbędne, by przeglądarka rozpoznała i rozpakowała zakodowaną treść z odpowiedzi http.
Moduł mod_deflate jest specjalnie przystosowanym do tych celów modułem Apache – odpowiada on za ustawianie i wysyłanie skompresowanych danych, co przyczynia się do sporych oszczędności – zarówno dla właściciela strony, jak i odwiedzającego.
Mniejszy transfer oznacza niższe koszty dla Ciebie. Mniejszy rozmiar danych do pobrania przez klienta oznacza dla użytkownika szybsze wygenerowanie dokumentu w przeglądarce.
Jedyną wadą jest większe zużycie procesora przez Twój serwis. Przy ogromnych serwisach to może być problem, jednak jeszcze nie spotkałem się z tym problemem w praktyce, stąd nie napiszę o dostępnych rozwiązaniach – mógłbym jedynie teoretyzować, więc lepiej przemilczę temat.
Odpalamy mod_deflate
Na początek należy włączyć ten moduł do serwera Apache. O instalacji/aktywacji poszczególnych modułów można poczytać w wielu miejscach, także odsyłam do zewnętrznych źródeł.
Gdy już moduł jest uaktywniony, możemy zabrać się za określenie ustawień konfiguracyjnych. Dla swoich serwisów stosuję następujący zapis:
1 2 3 4 5 6 | <IfModule mod_deflate.c> AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE text/javascript application/x-javascript </IfModule> |
Oznacza to, że kompresja jest wykonywana na plikach takich jak: pliki tekstowe, dokumenty HTML, arkusze stylów CSS oraz pliki skryptów JS.
Dlaczego akurat takie pliki, a nie inne? Dlaczego nie dokonuję kompresji grafiki? Otóż, kompresja ta jest opłacalna tylko na plikach tekstowych. Tutaj stopień kompresji jest naprawdę spory (im większy i mniej skomplikowany dokument, tym wyższy procent kompresji).
Jeśli chodzi o pliki graficzne, pliki wykonywalne czy inne, skompilowane i zamknięte aplikacje, kompresja niewiele pomoże. Lepiej więc sobie podarować wykonywanie kompresji na tych plikach, a możliwości obliczeniowe procesora wykorzystać w bardziej optymalny sposób :-).
1 2 3 | <IfModule mod_deflate.c> # właściwe reguły konfiguracyjne modułu </IfModule> |
Powyższy zapis oznacza, że ustawienia i operacje konfiguracyjne dla modułu mod_deflate zostaną wykonane tylko wtedy, gdy zainstalowano moduł mod_deflate.
W związku z tym nie zostanie wygenerowany błąd o kodzie 500 (Internal Server Error) na serwerach nie obsługujących tego modułu (w przypadku braku dyrektywy IfModule, zamiast strony ukazałby się zapewne wszystkim znany 500 Internal Server Error).
Dlatego też powyższy kod konfiguracyjny można śmiało zamieszczać na każdym serwerze Apache bez większych konsekwencji ubocznych. Jeśli moduł jest zainstalowany to zadziała – jeśli nie jest zainstalowany to powyższe reguły zostaną pominięte.
Dyrektywa IfModule może być także wykorzystywana przy używaniu innych modułów Apache, tj. mod_rewrite, mod_proxy, mod_access, etc.
Dodatkowe wymagania modułu mod_deflate
Aby kompresja przy pomocy modułu mod_deflate została prawidłowo wykonana, musi zostać spełniony jeden warunek.
Klient musi wysłać nagłówek Accept-Encoding, zawierający zwrot gzip. Właśnie przy pomocy tego typu kompresji działa deflate, stąd taka konieczność. Jeśli klient nie odeśle takiego nagłówka to oznacza, że nie będzie potrafił rozpakować przesłanych danych, więc kompresja nie ma racji bytu.
Kod nagłówka odsyłanego przez serwer, na którym została wykonana kompresja za pomocą modułu mod_deflate będzie zawierać takie nagłówki jak Content-Encoding oraz Vary.
Pierwszy z nich odsyła do klienta informację o sposobie kompresji, czyli gzip. Wskaże to klientowi (np. przeglądarce), iż trafiana do niego zawartość musi być odkodowana, a dopiero potem dalej przetwarzana. Natomiast nagłówek Vary informuje klienta o tym, że kodowanie jest wynikiem uzgadniania odpowiedzi.
Konfiguracja na poziomie serwera
Powyższe ustawienia konfiguracyjne można stosować dla dokumentów .htaccess. Jeśli chcemy dokładniejszej konfiguracji, musimy modyfikować plik konfiguracyjny serwera Apache.
Do dyspozycji mamy takie dyrektywy, jak:
DeflateMemLevel
Wskazuje maksymalną ilość pamięci, jaka zostanie wykorzystana w czasie kompresji. Zakres: 1-9. Im większa wartość, tym zostanie przydzielone więcej pamięci podczas kompresji.
DeflateWindowSize
Określa rozmiar bufora historii kompresji, czyli ilość miejsca przydzielonego dla dokumentów przechowywanych w buforze. Zakres: 1-15. Im większa wartość tej dyrektywy, tym zostanie przydzielone więcej miejsca dla historii kompresji w buforze.
DeflateFilterNote
Tworzy notkę z informacją o wynikach kompresji dla dokumentów. Informacja taka jest przydatna podczas analizowania plików dziennika i logów serwera.
Przykładowe ustawienia na poziomie serwera:
1 2 3 | DeflateMemLevel 7 DeflateWindowSize 15 DeflateFilterNote cprss_by_gzip |
Alternatywne sposoby kompresji dokumentów
Powyższe rozwiązanie jest banalnie proste, do czego każdy już pewnie sam doszedł. Jak więc zastosować kompresję w sposób bardziej uniwersalny?
Blog jest w dużej mierze poświęcony PHP, więc mowa oczywiście o zewnętrznym języku skryptowym, jakim jest właśnie PHP. PHP posiada funkcjonalność odpowiedzialną za kompresję, więc nie ma problemu napisać klasę odpowiadającą za przesyłanie do klienta spakowanych danych.
Już niebawem postaram się napisać kod odpowiedzialny za takie zadanie. Sam też będę musiał się przerzucić w przyszłych projektach na rozwiązanie bezpośrednio w PHP, zamiast przy pomocy Apache. Nigdy nie wiadomo, czy kiedyś będzie potrzebna migracja do innego, lepszego serwera (nginx, Lighthttpd). Lepiej ubezpieczyć się zawczasu.
Podsumowanie
Jak można wyżej przeczytać, niewielkim nakładem pracy można zyskać naprawdę wiele. Polecam kompresję każdemu programiście, który chce, by jego aplikacje działały szybko i optymalnie.
Tutaj mam także pytanie do Was, innych programistów. W jaki sposób rozwiązujecie problem kompresji na swoich stronach internetowych? Za pośrednictwem serwera, a może przy użyciu języka PHP/innego? Czy konkretne frameworki posiadają wsparcie dla tego typu działań? No a może niektórzy nie używają wcale kompresji i mają ku temu poważne powody?
Z przyjemnością się dowiem o działaniach, jakie podejmują inni programiści. Za wszelkie porady będę wdzięczny :-).
A jak to się ma do gzip’a?
mod_deflate właśnie na poziomie serwera włącza kompresję dla wyżej wymienionych typów plików. A kompresja jest wykonywana właśnie przy pomocy gzip’a ;)
Wikipedia tak to tłumaczy:
Zamiast do każdego pliku PHP dołączać nagłówek Content-Encoding: gzip oraz wrzucać wszystko do gzencode możemy na poziomie serwera to załatwić w kilku linijkach kodu :-) Dużo mniej roboty, choć rozwiązanie mniej elastyczne (działa tylko z Apache, które powoli „wychodzi z mody”).
Nie powiedziałbym, że apache wychodzi z mody. W dalszym ciągu ma się dobrze i jest instalowane na większości serwerów zarówno pod linuksem, free bsd jak i window$em :)
Obecnie jestem właśnie na etapie konfiguracji dedyka i pomyślałem właśnie o deflate. Pytanie jednak moje jest takie jak ma się włączenie tego modułu do wzrostu obciążenia procesora ? Przecież dodatkowe jego zasoby muszą być wykorzystane do skompresowania danych, które są potem wysyłane do przeglądarki klienta. Serwerek jaki konfiguruje oscyluje w granicach load 2 przy dwóch rdzeniach i 4GB RAM. Na serwerze jest kilkanaście stron, więc mieli dość mocno przy kilku tys odwiedzin dziennie.