Download: KnowHow_Apache_optymalizacja

Transkrypt

Download: KnowHow_Apache_optymalizacja
KNOW HOW
Dostrajanie Apache
Skuteczna optymalizacja serwerów WWW
Szybki jak strzała
Nie ma nic bardziej irytującego niż
serwer Apache, który nie radzi sobie
z odpowiadaniem na żądania klientów i działa zbyt wolno. Webmasterzy znajdują się pod ciągłą presją
i nieustannie próbują zapewnić
płynność działania serwisów WWW.
Przyczyn powolnego działania jest
wiele, ale wiele jest także sposobów
na rozwiązanie problemu „wąskiego
gardła”. CHRISTIAN KRUSE
G
dy użytkownicy zaczynają coraz
częściej narzekać na długi czas
pobierania dokumentów, webmaster musi coś z tym zrobić. Przyczyn opóźnień może być wiele: zbyt mała przepustowość sieci, przeciążenie serwera lub po prostu zbyt duża liczba zapytań generowana
przez użytkowników. W artykule zaprezentowano kilka sposobów przyspieszenie działania serwisów WWW. Omówione zostały
również sposoby testowania wprowadzonych zmian za pomocą prostych narzędzi
do pomiaru wydajności.
Problemy z siecią i routerem
Na pewno lepszą strategią, niż doraźne reagowanie na pojawiające się problemy, jest systematyczna kontrola systemu i zapobieganie potencjalnym kłopotom. Najbardziej prawdopodobnym źródłem problemów jest mała przepustowość sieci i powstawanie „wąskiego gardła” w miejscach styku z siecią WAN (router)
lub niestabilne parametry połączenia. Użytecznymi narzędziami diagnostycznymi w takiej sytuacji są tracepath oraz traceroute, które
pozwalają łatwo ustalić przebieg pakietów,
wielkość opóźnienia między kolejnymi skoka-
Listing 1. Wyniki działania tracepath.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
44
ckruse@shine:~ $ tracepath www.defunced.de
1?: [LOCALHOST] pmtu 1500
1: fogg.defunced.de (192.168.1.1)
2: 10.3.11.1 (10.3.11.1)
3: gwin-gw-gig00-112.HRZ.Uni-Dortmund.DE (129.217.129.190)
4: ar-essen2.g-win.dfn.de (188.1.44.33)
5: cr-essen1-ge4-0.g-win.dfn.de (188.1.86.1)
6: cr-frankfurt1-po8-1.g-win.dfn.de (188.1.18.89)
7: 188.1.80.42 (188.1.80.42)
8: gi-0-3-ffm2.noris.net (80.81.192.88)
9: ge0-2-151-nbg5.noris.net (62.128.0.209)
10: no.gi-5-1.RS8K1.RZ2.hetzner.de (213.133.96.25)
11: et-1-16.RS3K1.RZ2.hetzner.de (213.133.96.230)
12: srv001.occuris.de (213.133.103.124)
Resume: pmtu 1500 hops 12 back 12
Luty 2004
www.linux-magazine.pl
2.625ms
5.109ms
13.403ms
222.119ms
12.839ms
24.964ms
24.872ms
26.466ms
40.772ms
31.012ms
32.433ms
38.802ms
mi itp. Takie testy trzeba wykonywać redukując parametr TTL (Time to Live) i oczekując aż
router zwróci błąd przekroczenia czasu oczekiwania (TIME_EXCEEDED).
Pole TTL najczęściej określa ilość skoków
(hops) dozwolonych przy przekazywaniu pakietu przez sieć. Pozwala to administratorom
bliżej analizować problemy z połączeniem. Listing 1 pokazuje następujący przykład: router
w 4 skoku, ar-essen2.g-win.dfn.de, odpowiada
dość wolno. Tym niemniej czas 0,2 sekundy
nie jest jeszcze krytyczną wartością, należy zatem założyć, że „wąskie gardło” występuje jednak gdzieś indziej.
Następnym krokiem jest analiza obciążenia
serwera. Najlepszym sposobem sprawdzenia
Tabela 1. Najważniejsze
moduły Apache.
reached
Nazwa modułu
Nazwa modułu
env_module
alias_module
config_log_module
rewrite_module
mime_module
access_module
includes_module
auth_module
autoindex_module
setenvif_module
dir_module
headers_module
cgi_module
expires_module
action_module
php4_module
gzip_module
Dostrajanie Apache
się jednak także tak,
że wykresy obciążenia serwera stale
przedstawiają niskie
wartości, ale poziom
ruchu w sieci jest
zdecydowanie zbyt
wysoki.
Czy
serwer jest
przeciążony?
KNOW HOW
oprogramowania z odpowiednią flagą kompilatora. Wiele popularnych dystrybucji zawiera
pakiet Apache, skompilowany do pracy na
procesorach serii 386 w celu zachowania kompatybilności.
Rekompilacji można dokonać ustawiając
flagi kompilacji stosownie do posiadanej platformy sprzętowej. Jeśli twój serwer bazuje na
procesorze Athlon (zobacz poniższą tabelę
„Środowisko testowe”), możesz użyć poniższego zestawu flag:
Fakt, że serwer jest
CFLAGS='-march=athlon U
mocno obciążony,
-fexpensive-optimizations -O3'
niekoniecznie musi
Rysunek 1. Zmiana parametru Connection Timeout w pliku konfigurastanowić powód do
cyjnym Apache może zwiększyć wydajność.
Flagi te wskazują kompilatorowi, żeby generozmartwień.
Duże
wał kod maszynowy działający wyłącznie na
i często używane dokumenty, mają tendencję
procesorach typu Athlon. W naszym przykłatego jest monitorowanie serwera podczas stando generowania dużego obciążenia. W wielu
dzie poziom optymalizacji jest ustawiony na 3,
dardowej pracy, przez łączenie się do konsoli
przypadkach administrator niewiele może
co pozwala kompilatorowi użyć zoptymalizonp. przy pomocy SSH. Narzędzia takie jak top
z tym zrobić. Pierwszą rzeczą, której można
wanych metod (kosztem dłuższego czasu komi ps dostarczają ogólnych wskazówek, podobnie
spróbować, jest ponowne przekompilowanie
pilacji i kompatybilności).
wartość uptime, która pozwoli ustalić poziom
bieżącego obciążenia serwera. Narzędzie Apachetop, opisywane w Linux Magazine [3], bęŚrodowisko testowe
dzie również bardzo przydatne w przeprowana Gentoo Linux 1.4 z jądrem 2.4.22,
dzaniu analizy. Niestety, nie ma żadnej gwai Perl 5.8.0. Moje podstawowe narzęrancji, że tak zidentyfikowane „wąskie gardzie testujące wydajność, to skrypt nadło” jest elementem stałym; tak naprawdę
pisany przeze mnie w Perlu, który
można ściągnąć z [1]. Na rysunku
może ono mieć charakter chwilowy i powstać
2 przedstawiono fragment jego dzianp. w wyniku przerw w pracy urządzeń sieciołania. Skrypt ściąga adres URL, podawych i awarii łącz. Rozwiązaniem tego prony jako argument przy jego wywołablemu jest użycie programu MRTG [4], słuniu, wraz ze wszystkimi odwołaniami
żącego do rejestrowania działań serwera
potrzebnymi do pomiarów. Skrypt
w dłuższym przedziale czasu. Opis przykładomierzy czas potrzebny do wykonania
wej instalacji MRTG znajduje się w [5].
tego (zobacz rysunek 3).
Analizowanie wykresów MRTG zwykle
Rysunek 2. Fragmenty skryptu testowego autora
Drugie narzędzie to dostarczony
ujawnia, że serwer jest przeładowany lub ponapisanego w Perlu, do ściągnięcia ze stron WWW
z Apache program ab [2]. Służy on
ziom ruchu jest zbyt wysoki. Wykresy średnieLinux Magazine.
głównie do pomiarów obciążenia. Aby
go obciążenia oraz obciążenia procesora, to
określić jego poziom, narzędzie to syTesty wydajności są używane do określenia
wskaźniki pozwalające łatwo wykryć zbyt duże
muluje dużą liczbę jednoczesnych zapytań,
efektywności dokonanej optymalizacji. Doobciążenie serwera. Wykaz liczby aktywnych
następnie mierzy liczbę zapytań obsługiwabrym kryterium porównawczym jest mierzeprocesów pozwala zidentyfikować winowajcę.
nych przez serwer w czasie jednej sekundy
nie czasu między otrzymaniem przez serwer
oraz czas potrzebny Apache na ich obsługę.
Jeśli liczba procesów pozostaje stała, powinnizapytania, a dostarczeniem odpowiedzi na
śmy poszukać procesu, który wymknął się spod
nie. Aby to sprawdzić, uruchomiłem
kontroli i działa wadliwie, zajmując pamięć
2 komputery PC i podłączyłem je do
i czas procesora.
sieci wewnętrznej 100 MB. Mój serwer
(AMD Athlon 600 z 64 MB pamięci
Jednak jeśli liczba procesów się zmienia,
SD-RAM) pracował na FreeBSD 4.6
należy sprawdzić skrypty CGI, które również
i Apache 1.3.27.
mogą blokować zasoby. W tym celu przyda
Charakterystyki serwera WWW opisasię plik Access.log z Apache oraz lista procene w tym artykule odnoszą się również
sów (uzyskana programem top) zużywających
do Apache 2, o ile nie zaznaczono
najwięcej zasobów, obejmujące przedział czainaczej. Do symulowania prędkości
su, w którym serwer był w znacznym stopniu
ISDN zainstalowałem również moduł
obciążony. Dzięki nim można się dowiedzieć,
Mod_bandwidth, aby różnice w wydajktóre adresy URL były najczęściej wywołyRysunek 3. Skrypt testowy autora w akcji. Ściąga
ności były bardziej widoczne.
wane. Ta informacja pozwala administratowybrany adres URL i mierzy czas potrzebny na tą
Maszyny klienckie (AMD Duron 800
rom zlokalizować skrypt lub program odpooperację.
z 312 MB pamięci SD-RAM) działały
wiedzialny za przeciążanie serwera. Zdarza
www.linux-magazine.pl
Luty 2004
45
KNOW HOW
Dostrajanie Apache
Wiele modułów Apache podczas obsługi
zapytań tworzy pliki tymczasowe; PHP tworzy jednorazowe pliki, ułatwiające zarządzanie sesją. Dlatego następny krok optymalizacji, to przeniesienie katalogu /tmp z dysku
twardego do pamięci (RAM-dysk), standardowo o rozmiarze około 128 MB. Mimo, że Linux używa bardzo efektywnej strategii buforowania danych, RAM-dysk znacznie przyspiesza czas reakcji serwera.
Dostrajanie HTTPD
Sam serwer Apache posiada duże możliwości
optymalizacji. Chociaż podstawowa domyślna konfiguracja zazwyczaj wystarcza, niektóre dystrybucje próbują ładować zbyt wiele
zbędnych modułów. Do normalnej pracy po-
Standardowe CGI:
Mordercy wydajności
Skrypty CGI, działające na serwerze
WWW, należy dokładnie przeanalizować.
Te niewątpliwie użyteczne pogramy często
wywołują problemy z wydajnością, ponieważ uruchomienie ich wymaga przetworzenia plików binarnych.
Usunąłem rzeczywiste nazwy hostów, ale
poniższy przykład jest z życia wzięty: Serwer
WWW, działający w środowisku produkcyjnym, miał bardzo duży i skomplikowany
skrypt CGI napisany w Perlu. Gdy serwer
zaczął mieć problemy z dużym obciążeniem, odpowiedzialny za jego działanie zespół zmodyfikował zasady działania skryptu tak, aby sprawdzał średnie obciążenie
i usuwał procesy CGI w przypadku wykrycia przeciążenia. Skutki były odwrotne do
zamierzonych: obciążenie wciąż było bardzo duże, a uruchamianie interpretera
i przetwarzanie skryptów zajmowało bardzo dużo zasobów systemu.
Następnym krokiem było napisanie
804–bajtowego programu w C, który podejmował decyzje w zależności od wydajności.
Gdy obciążenie było zbyt duże, generował
informację o błędzie, jeśli nie – uruchamiał
oryginalny skrypt CGI. Rozwiązanie to okazało się bardzo efektywne, system radził sobie z dużym obciążeniem znacznie lepiej niż
w poprzednim przypadku.
Programiści mogą iść jeszcze krok dalej
i napisać moduł mod_loadavg do serwera
Apache i ograniczyć w jeszcze większym
stopniu obciążenie serwera. Moduły tego
typu pozwalają zrezygnować z wywoływania interpreterów języków programowania. Moduły Apache są dostępne dla
wszystkich najważniejszych języków programowania, np.: mod_perl, mod_php,
mod_ruby, mod_fastcgi.
46
Luty 2004
trzebne są wyłącznie moduły wymienione
w Tabeli 1. Usunięcie zbędnych modułów
zmniejszy rozmiar pamięci zajmowany przez
proces HTTPD, skróci również czas obsługi
zapytań. Dzieje się tak, ponieważ dla każdego obsługiwanego zapytania Apache musi
sprawdzić każdy aktywny moduł pod kątem
przydatności do jego obsługi. Przyjrzyjmy się
teraz jawnym parametrom zapisanym w pliku konfiguracyjnym serwera.
Doświadczenie pokazuje, że np. zmniejszenie wartości connection timeout w parametrze Timeout pliku konfiguracyjnego może wiele zmienić. Czy naprawdę trzeba czekać aż 300 sekund,
żeby serwer zamknął połączenie, nie doczekawszy się nowego pakiet lub zapytania? Takie powolne zapytania blokują procesy podrzędne
i uniemożliwiają przyjmowanie nowych połączeń, które Apache mógłby obsłużyć w międzyczasie. Czas oczekiwania wynoszący 120–150
sekund powinien wystarczyć, nawet w przypadku klientów korzystających z wolniejszych połączeń internetowych (zobacz Rysunek 1).
Administratorzy powinni również sprawdzić, czy opcja Keep Alive jest ustawiona na On.
Ten parametr włącza obsługę zapytań przy pomocy Keep Alive. Pozwala ona klientom używać
jednego połączenia do obsługi wielu zapytań.
W innym przypadku klient musi korzystać
z nowego połączenia dla każdego nowego zapytania, a to wiąże się za każdym razem z przejściem przez procedurę nawiązywania połączenia i niepotrzebnym wykorzystaniem trzech
dodatkowych pakietów. Przy obciążeniu na poziomie 50 zapytań na sekundę, oznacza to 9000
pakietów na minutę, potrzebnych tylko i wyłącznie na nawiązanie połączeń. W ten sposób,
przyjmując, że 3 klientów generuje 50 zapytań,
włączenie opcji Keep Alive zredukuje liczbę połączeń na sekundę do 3, a liczbę pakietów potrzebnych do nawiązania tych połączeń do 540.
Redukowanie opóźnień
Parametr KeepAliveTimeout powinien mieć
możliwie niską wartość – zwykle wystarcza 15
sekund. Parametr MaxSpareServers ogranicza
liczbę bezczynnych procesów httpd. Powoduje
to zmniejszenie liczby procesów httpd w okresach mniejszego obciążenia serwera.
Oznacza to również, że Apache będzie musiał podzielić kilka nowych procesów httpd
w celu obsłużenia zwiększającego się obciążenia. W przypadku serwisów narażonych na
czasowe skrajne obciążenia, administratorzy
powinni jednak zablokować (wykomentować)
ten parametr, monitorując jednocześnie wyniki i sprawdzając, czy efektywność serwera
wzrasta. Parametr MaxSpareServers powinien
być ustawiony w okresach mniejszego obciążenia, dzięki czemu będziesz miał kontrolę
nad ilością procesów httpd.
Zupełnie inną funkcję pełni parametr MinSpareServers. Określa on liczbę bezczynnych
procesów, które powinien podtrzymywać w pamięci serwer. Procesy te stanowią rodzaj bufora w razie pojawienia się drastycznych skoków
obciążenia. Pamiętaj, że sposób reakcji serwera
na poziom obciążenia zależny jest od wyboru
odpowiednich modułów. Serwer będzie się zachowywał inaczej w przypadku użycia modułu
MPM – Multiprocessing Module [6, 7] dostępnego dla Apache 2. Wówczas możesz skorzystać z parametrów w MaxSpareThreads i MinSpareThreads. W tym przypadku te wartości
Listing 2. Rezultaty przed tuningiem.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
Concurrency Level:
Time taken for tests:
Complete requests:
Failed requests:
Write errors:
Total transferred:
HTML transferred:
Requests per second:
Time per request:
Time per request:
Transfer rate:
10
2.842457 seconds
100
0
0
11023620 bytes
10994986 bytes
35.18 [#/sec] (mean)
284.246 [ms] (mean)
28.425 [ms] (mean, across all concurrent requests)
3787.22 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd]
Connect:
0
0 1.0
Processing:
39 278 342.6
Waiting:
-83 -22 19.1
Total:
39 278 342.8
www.linux-magazine.pl
median max
0
5
105
1012
-21
1
106
1012
Dostrajanie Apache
jąc w każdej fazie jednocześnie po 10 zapytań.
Listing 2 pokazuje fragmenty wyników zawierające najważniejsze wartości. Warto spojrzeć
na ciekawe wykresy Requests per second (zapytania na sekundę) i Time per request (czas potrzebny na obsłużenie zapytania). Uzyskane
tu średnie wartości są interesujące – jest to
około 35 zapytań na sekundę i 28 milisekund
na obsługę każdego zapytania. Po wykonaniu
tego testu należy zmienić konfigurację serwera (optymalizując go) i ponownie wykonać test
wydajności. Listing 3 pokazuje przykładowe
wyniki po wykonaniu optymalizacji. Wygląda
na to, że w tym wypadku proces optymalizacji
powiódł się całkowicie. Można ostrożnie założyć, że teraz serwer będzie mógł obsłużyć dwukrotnie większą liczbę zapytań.
Listing 3. Wydajność po tuningu.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
Concurrency Level:
Time taken for tests:
Complete requests:
Failed requests:
Write errors:
Total transferred:
HTML transferred:
Requests per second:
Time per request:
Time per request:
Transfer rate:
10
1.58400 seconds
100
0
0
11290258 bytes
11261068 bytes
94.48 [#/sec] (mean)
105.840 [ms] (mean)
10.584 [ms] (mean, across all concurrent requests)
10416.67 [Kbytes/sec] received
Connection Times (ms)
min mean [+/-sd] median max
Connect:
0
0
0.3
0
3
Processing:
34
98
21.1
95
155
Waiting:
-102 -46
17.9 -42
0
Total:
34
98
21.0
95
155
odnoszą się do liczby wątków w procesie Apache. Ogólnie rzecz biorąc, jest to lepsze rozwiązanie, ponieważ Apache 2 powinien mieć
mniejsze problemy z tworzeniem nowych wątków niż nowych procesów. Wątek nie musi posiadać własnego obszaru pamięci, do którego
proces musiałby być skopiowany. Ponadto wątek nie posiada własnego identyfikatora (process ID), ale wraz z pozostałymi wątkami współdzieli ID głównego procesu.
W poszukiwaniu kompromisu
Kolejnym istotnym parametrem jest MaxRequestsPerChild, który usuwa procesy potomne
po przetworzeniu pewnej liczby zapytań i tworzy nowe procesy potomne. Jest to przydatna
funkcja, ponieważ niektóre biblioteki i moduły są podatne na „wycieki pamięci” (memory leaks) i należy je co pewien czas przeładować, żeby oczyścić pamięć. Należy jednak wykonać
dokładne testy przed włączeniem tego parametru, w celu sprawdzenia, czy stosowanie go
jest na pewno potrzebne.
Jeśli okaże się, że liczba procesów Apache
rośnie gwałtownie podczas okresów wyższego
obciążenia (do sprawdzenia tego możesz użyć
narzędzia top), w zasadzie nie ma innego wyjścia, jak użycie tego parametru. W tym przypadku należy ustawić wysoką wartość, jest ona
zależna od konfiguracji systemu i musi być dobrana metodą prób i błędów. Jest to zawsze
kompromis między wydajnością, a stopniem
wykorzystania zasobów pamięci.
Drugim „kompromisowym” parametrem
jest HostnameLookups. Jeśli priorytetem jest
szybkość pracy, należy go ustawić na Off. Uaktywnienie tej opcji wymusza dla każdego zapy-
KNOW HOW
Optymalizacja
na poziomie HTTP
tania odwrócone (reverse) wyszukiwanie DNS.
Powoduje to z kolei wysłanie przynajmniej jednego zapytania do serwera DNS i prowadzi zazwyczaj do generowania kolejnych zapytań
DNS do serwerów nazw po stronie zdalnego
klienta. Powoduje to nie tylko zwiększony ruch
w sieci, ale także zabiera dużo czasu.
Na ile skuteczna
jest optymalizacja Apache?
Dość trudno jest ocenić efekt wykonanej optymalizacji. Skrypt [1] nie nadaje się do przetestowania wprowadzonych zmian, ponieważ
nie generuje żadnego obciążenia na serwerze.
Test Apache ab (wersja 2, [2]) powinien jednak dostarczyć oczekiwanych informacji (zobacz ramka „Środowisko testowe”). Uruchom
go przed rozpoczęciem optymalizowania:
ckruse@shine:~ $ ab2 -n 100 U
-c 10 http://rain/article/
Program uruchamia 100 faz zapytań, wykonu-
Optymalizacja na poziomie protokołu HTTP
jest związana głównie z obniżaniem poziomu
ruchu i zmniejszaniem liczby zapytań, przy
czym pomocne będą nagłówki warunkowe
(conditional header) i nagłówki buforu (caching
header). Nagłówki buforu mówią klientowi (np.
przeglądarce WWW), że nie ma potrzeby ponownego pobierania przez określony czas pewnej części danych. Jest to bardzo użyteczne
w przypadku statycznego kodu HTML lub arkuszy stylów CSS. Nagłówek Expires wskazuje,
kiedy dokument powinien zostać ponownie
pobrany (zobacz Listing 4).
Jeśli chcesz przekazać do UA (User Agent
– może to być przeglądarka, proxy lub inny
klient), że dokument stał się nieaktualny natychmiast po wygenerowaniu przez Apache
i trzeba go pobierać za każdym razem, należy
w polu nagłówka wstawić wartość Date. Wartości takie jak now lub 0 są niewłaściwe, ale
są akceptowane w celu zwiększenia poziomu
tolerancji błędów i przyrównywane do poprzedniej wartości. Od klienta zależy, czy
uwzględni tę informację.
Listing 4. Ustawianie nagłówków Expires i Cache-Control.
1 ExpiresActive On
02 ExpiresByType text/html „access plus 1 month”
03 ExpiresByType text/css „access plus 6 month”
04 ExpiresByType text/javascript „access plus 6 month”
05 ExpiresByType image/gif „access plus 6 month”
06 ExpiresByType image/jpeg „access plus 6 month”
07 ExpiresByType image/png „access plus 6 month”
08
09 <Files ~ "\.(js|css|gif|jpe?g|png)$">
10 Header append Cache-Control "public"
11 </Files>
www.linux-magazine.pl
Luty 2004
47
KNOW HOW
Dostrajanie Apache
Listing 5. Przykład
zapytania HTTP.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
ckruse@shine:~ $ telnet rain 80
Trying 192.168.1.3...
Connected to rain.defunced.de.
Escape character is '^]'
GET /article/ HTTP/1.1
Host: rain
Connection: close
HTTP/1.1 200 OK
Date: Sun, 09 Nov 2003 19:52:04 GMT
Server: Apache/1.3.27 (Unix)
PHP/4.2.3 AuthMySQL/2.20
Cache-Control: max-age=2592000
Expires: Tue, 09 Dec 2003 19:52:04
GMT
Last-Modified: Tue, 04 Nov 2003
23:50:42 GMT
ETag: "a3a068-1a9d9-3fa83b52"
Accept-Ranges: bytes
Content-Length: 109017
Connection: close
Content-Type: text/html
15
16
17
18
19
20
21 <I>HTML contents<I>
Nagłówek Cache-Control jest bardziej precyzyjny. Określa ściśle polecenia i parametry buforowania, które każdy klient HTTP zgodny
z RFC, musi obsługiwać. Składnia dla Cache-Control jest nieco inna niż dla Expires. Okres
ważności dokumentu jest określany przez parametr max-age=wartość. Wartość jest okresem
ważności w sekundach, liczonym od czasu
określonego w polu Date. Ustawiając tę wartość
na 0 określamy, że dokument nie powinien być
w ogóle buforowany, jednak takie rozwiązanie
nie jest zalecane.
Nagłówki
Atrybuty publiczne w nagłówku Cache-Control
mogą w pewnych okolicznościach zwiększyć
szybkość, ponieważ zezwalają serwerowi proxy na większą swobodę w interpretacji. Jeśli
tak poinstruowany serwer proxy odbierze zapytanie, które nie powinno być buforowane,
np. zapytanie autoryzacyjne używające HTTP-Auth, może je zignorować i mimo wszystko
zapamiętywać.
Obydwa nagłówki wymagają do pracy modułów mod_expires i mod_headers. Administratorzy mogą użyć mod_expires do określenia daty
wygaśnięcia ważności dokumentu. Jednakże
moduł ten nie obsługuje atrybutu publicznego,
więc oznacza to, że będzie potrzebny również
mod_headers, aby zezwolić plikom graficznym,
48
Luty 2004
skryptom Javascript oraz plikom CSS na jego
użycie. Listing 4 pokazuje przykład zapytania
HTTP do skonfigurowanego w ten sposób serwera. Zapytanie pokazane na Listingu 5 powinno zostać zapamiętane przez UA (proxy
lub przeglądarkę) na okres miesiąca, bez konieczności kontaktowania się w międzyczasie
UA z serwerem. Doświadczenie pokazuje jednak, że UA buforują wyniki tylko na krótki
czas, najczęściej około dwóch dni, a następnie
używają nagłówków warunkowych do sprawdzenia, czy zapamiętana wersja jest aktualna
lub czy wymaga uaktualnienia. Do tego celu
służy grupa nagłówków rozpoczynających się
od If. Dopuszczalne są nagłówki takie jak If-Match, If-Modified-Since, If-None-Match, If-Range oraz If-Unmodified-Since.
Jednak w praktyce nie są one używane, za
wyjątkiem If-None-Match (Opera 7 i nowsza
oraz Mozilla) i If-Modified-Since (Mozilla, Opera 7, MS Internet Explorer 5.5 oraz nowsze).
Pozostałe nagłówki zostały opisane w [8].
Mierzenie wydajności
Nagłówki warunkowe
Techniki kompresji
Wszystkie nagłówki warunkowe odwołują się
do pól, które serwer generuje podczas pierwszego zapytania. If-Modified-Since odwołuje się
do pola Last-Modified, które zawiera datę ostatniej modyfikacji dokumentu. Nagłówek If-None-Match odwołuje się do ETag, sumy kontrolnej dokumentu.
UA zachowuje te wartości i odpowiednio
formułuje zapytania (zobacz Listing 6). Jak widać, serwer zwraca odpowiedź 304 Not Modified
('niezmodyfikowany') i kilka innych nagłówków, ale nie odsyła żadnej zawartości.
Kilka słów należy poświęcić skryptom
CGI. Skrypt CGI powinien wysyłać nagłówek Last-Modified lub ETag, umożliwiający
przeglądarce używanie algorytmów warunkowego polecenia GET. Ponadto skrypt musi także przetwarzać nagłówek, ponieważ
jest to wymagane do odpowiedniego formatowania daty (zwykle podawanego jako liczba sekund od 1970 roku). Dopiero wtedy
można sprawdzić, na podstawie informacji
o wersji w nagłówku If-Modified-Since, czy
dokument jest aktualny.
Podobnie jest w przypadku nagłówka If-None-Match: skrypt oblicza sumę kontrolną
i w ten sposób sprawdza, czy wersja dokumentu opisana w nagłówku jest aktualna. Jako algorytmu obliczającego sumę kontrolną można
użyć algorytmu haszującego, takiego jak na
przykład MD5. Zmienne środowiskowe CGI,
HTTP_IF_MODIFIED_SINCE
i HTTP_IF_NONE_MATCH umożliwiają dostęp do wartości w obu nagłówkach.
Kodowanie zawartości jest inną metodą optymalizowania HTTP. Wymaga ona wysłania
przez agenta użytkownika przy zapytaniu
o dokument nagłówka Accept-Encoding. Nagłówek określa sposób przetwarzania odpowiedni
dla zawartości i może zawierać takie wartości
jak: gzip [9] lub compress. Obie wartości okre-
www.linux-magazine.pl
Do zbadania efektywności optymalizacji można użyć skryptu [1] (patrz ramka 'Środowisko
testowe'):
ckruse@shine:~ $./measure.pl U
--base-url http://rain/article/
Getting http://rain/article/...
[...]
Time elapsed: 4.642203 seconds
Włączenie obsługi nagłówków warunkowych
sprawiło, że całe zapytanie jest przetwarzane
w czasie poniżej sekundy.
ckruse@shine:~ $./measure.pl U
--send-if-modified-since U
--send-if-none-match --base-url U
http://rain/article/
Getting http://rain/article/...
[...]
Time elapsed: 0.181876 seconds
Listing 6. Warunkowe
polecenie GET.
1 ckruse@shine:~ $ telnet rain 80
02 Trying 192.168.1.3...
03 Connected to rain.defunced.de.
04 Escape character is '^]'.
05 GET /article/ HTTP/1.1
06 Host: rain
07 Connection: close
08 If-Modified-Since: Tue, 04 Nov 2003
23:50:42 GMT
09 If-None-Match: "a3a068-1a9d93fa83b52"
10
11 HTTP/1.1 304 Not Modified
12 Date: Sun, 09 Nov 2003 20:28:43 GMT
13 Server: Apache/1.3.27 (Unix)
PHP/4.2.3 AuthMySQL/2.20
14 Connection: close
15 ETag: "a3a068-1a9d9-3fa83b52"
16 Expires: Tue, 09 Dec 2003 20:28:43
GMT
17 Cache-Control: max-age=2592000
18
19 Connection closed by foreign host.
Dostrajanie Apache
Optymalizacja
na poziomie kodu HTML
Pliki HTML posiadają największy potencjał
optymalizacyjny. Znaczna część kodu HTML,
zwłaszcza przygotowywana dla serwisów firmowych i komercyjnych, jest dostarczana
przez projektantów używających edytorów
WYSIWYG, takich jak np. Dreamweaver.
Edytory te generują jednak dużo nadmiarowego kodu, który bardzo często można skrócić aż
o 50 %, bez uszczerbku dla kodu. Generalnie
zaleca się usuwanie możliwie wielu sekwencji
formatujących z pliku HTML i umieszczanie
ich w plikach arkuszy stylów CSS. Z tym zadaniem radzą sobie doskonale nowe edytory
WYSIWYG, niestety w przeciwieństwie do ich
użytkowników...
W odróżnieniu od sekwencji formatujących
umieszczonych bezpośrednio w plikach
HTML, pliki CSS są ładowane tylko raz, co
oznacza, że serwer HTTP tylko raz wysyła sekwencje formatujące. Należy również unikać
nadmiernego zagnieżdżania tabeli, jak to się
często dzieje w przypadku programu Dreamweaver. Projektanci stron nie powinni traktować kodu wygenerowanego przez tego rodzaju
programy jako produktu ostatecznego, lecz jedynie jako prototypu. Taki kod należy upo-
rządkować i oczyścić ze zbędnych sekwencji,
używając w tym celu przykładowo narzędzia
HTML-Tidy [10].
Obrazy i grafika
Projektanci stron mogą znacząco ograniczyć
ruch w sieci, zwracając więcej uwagi na obróbkę obrazów i grafiki. Najpopularniejsze formaty obsługiwane przez większość przeglądarek to GIF, JPEG i PNG. Proste rysunki i animacje, to przeważnie pliki GIF, natomiast format JPEG jest używany do zdjęć i obrazów wysokiej jakości – mimo iż algorytm JPEG obniża jakość obrazu.
Format GIF nie jest przydatny do tego celu,
ponieważ może obsługiwać jedynie 256 kolorów. Jeśli najważniejsza jest jakość, to najlepszym wyborem będzie skompresowany format
PNG, chociaż rozmiar pliku może być trochę
większy niż porównywalnego pliku JPEG.
Często spotyka się duże pliki graficzne
w wysokiej rozdzielczości, skalowane na stronie WWW przy użyciu parametrów width i height. Takie rozwiązanie ma dwie wady: po
pierwsze, oznacza to konieczność niepotrzebnego przesłania dużego pliku. Po drugie, jakość obrazu jest niższa, ponieważ dowolny program do obróbki grafiki pozwala uzyskać dużo
lepsze efekty wygładzania i korekcji przy
zmniejszaniu pliku niż wewnętrzne mechanizmy przeglądarki.
Kiedyś projektanci stron byli ograniczeni
powolnymi modemami 14,400 Kb/s i wysoką
ceną miejsca na serwerach. Obecnie nie stanowi to już problemu, jednak użytkownicy przyzwyczaili się do zmniejszania obrazków i pozwalają przeglądarce powiększać je z powrotem. Niestety UA niezbyt dobrze radzą sobie
z takim zadaniem. Najlepszym rozwiązaniem
wydaje się być dobranie takiej skali dla obrazów, aby były wyświetlane w oryginalnym rozmiarze – jest to doskonały kompromis między
rozmiarem i jakością pliku.
Spacje i znaczniki nowej linii
HTML jest językiem nie narzucającym wymagań dotyczących formatowania, co pozwala
usunąć zbędne spacje i znaki nowej linii. Dla
UA jest obojętne, czy kod HTML jest ładnie
sformatowany, czy też jest to ciąg znaków
w jednym wierszu. Umożliwia to dalsze ograniczenie ruchu w sieci, podobnie jak w przypadku konwersji znaków końca linii w Windows na
znaki końca linii w Uniksie, które zajmują jeden bajt zamiast dwóch. Każdy nowoczesny
edytor HTML powinien posiadać tę opcję.
Użytkownicy Apache 2 mogą użyć w tym celu modułu mod_blanks. Użytkownicy pozosta-
łych wersji Apache mogą uzyskać podobny
efekt, używając dwóch odrębnych wersji dokumentu – jednej do projektowania, drugiej do
publikacji. Po każdej zmianie w pliku do projektowania należy uruchomić prosty skrypt
(zobacz [11]). Usuwa on z wersji ostatecznej
zbędne spacje i znaki końca linii.
Zastosowanie wszystkich omówionych metod optymalizacji powinno przynieść oczekiwany efekt – lepszą wydajność serwisu. Będzie
to szczególnie dobrze widoczne w przypadku
średnio i bardzo obciążonych serwerów. Aby
dokładnie określić wpływ wprowadzonych
zmian na działanie systemu, należy zawsze
przeprowadzać testy wydajności przed i po wykonaniu optymalizacji, używając w tym celu
technik omówionych powyżej.
■
INFO
[1] Skrypt autora artykułu do pomiaru
wydajności: http://www.linux-magazin.de/
Service/Listings/2004/01/Apache-Tuning
[2] Apache benchmarking tool: http://
httpd.apache.org/docs/programs/ab.html
[3] Charly Kühnast, „The Sysadmin's Daily
Grind: Apache Tracking”:
Linux Magazine, numer 38, strona 54
[4] Multi Router Traffic Grapher:
http://people.ee.ethz.ch/~oetiker/
webtools/mrtg
[5] Przykładowa instalacja MRTG:
http://www.defunced.de/mrtg
[6] Multiprocessing Module: http://
httpd.apache.org/docs-2.0/mpm.html
[7] T Grahammer, „Apache 2.0 – Rules
of Succession”: Linux Magazine,
numer 24, padźiernik 2002, strona 29
[8] HTTP RFC: ftp://ftp.rfc-editor.org/
in-notes/rfc2616.txt
[9] U. Keil, „Dynamic Webpage
Compression with Mod_gzip
and Apache”: Linux Magazine,
numer 24, październik 2002, strona 26
[10] HTML-Tidy:
http://sourceforge.net/projects/tidy
[11] Skrypt do usuwania spacji z plików HTML:
http://www.defunced.de/blanks.pl.gz
AUTOR
ślają algorytmy kompresowania zawartości
dokumentu, zanim zostanie ona wygenerowana przez serwer oraz sposób rozpakowania jej
po stronie klienta.
Metoda ta znacznie zmniejsza poziom ruchu
w sieci – nawet o 90 %. Ma jednak kilka zasadniczych wad: po pierwsze, nie wszyscy agenci
potrafią ją obsłużyć – np. Netscape 4 wysyła nagłówek Accept-Encoding z wartością gzip, jednak
przeglądarka nie obsługuje tej metody poprawnie. Po drugie, proces kompresji zmniejsza wydajność serwera, ponieważ każdy dokument
musi zostać odpowiednio spakowany. Po trzecie, technika ta może zostać nieprawidłowo zinterpretowana podczas przekazywania danych
przez Internet – wiele aplikacji filtrujących zawartość (content filters) usuwa po prostu nagłówek Accept-Encoding, nie sprawdzając go.
Ponadto większość serwerów proxy nie reaguje prawidłowo na nagłówek Vary, wymagany dla potrzeb kompresji. Lista nagłówków generowana przez Vary zależy od wariantu zapytania. Starsze wersje linuksowego proxy, Squid
HTTP, wyłączają wszelkiego rodzaju nagłówki
zawierające parametry ustalające sposoby zapamiętywania. Dlatego zalecamy dokładnie przemyśleć wszystkie zalety i wady wynikające ze
stosowania modułu mod_gzip. Szczególnie istotne jest to, kto będzie z serwera korzystać.
KNOW HOW
Christian Kruse studiuje informatykę na
uniwersytecie w Dortmundzie. Pracuje
dorywczo jako administrator i jest odpowiedzialny za wiele
serwerów pracujących pod kontrolą
Linuksa i FreeBDS.
www.linux-magazine.pl
Luty 2004
49