Apache Speedup

Door Cruz op dinsdag 26 mei 2009 18:56 - Reacties (7)
Categorie: Willekeurig, Views: 6.447

Zoals in eerdere posts beschreven sleutel ik aan een web-based applicatie. Nu valt er altijd wel wat aan de performance te verbeteren, door minder databasequeries toe te passen etc, maar ik las in een JSMin+ blogpost van crisp dat er een plugin voor een plugin van firefox is (YSlow voor Firebug) die de performance beoordeeld.

Dit gebeurt door middel van een handige scorekaart, dit is een voorbeeld resultaat (en tevens mijn eindresultaat):
http://www.urdland.com/images/yslow_klein.png
(Klikbaar voor groter plaatje)

Hierbij is een Content Delivery Network niet relevant voor een lokale webapplicatie, en met Expires-headers heb je eigenlijk geen ETags nodig. Cookie-free domains wil zeggen dat je plaatjes e.d. op een ander domein zet zodat bij GET requests vanuit de browser niet elke keer de inhoud van het cookie wordt meegestuurd: ook dit is niet relevant voor een lokale webapp.

Wat in eerste instantie een slechte score kreeg, zijn de volgende items:
  • Add Expires headers
  • Compress components with gzip
En deze zijn dus eenvoudig op te lossen door de apache configuratie te tweaken!

Om voor het nageslacht vast te leggen wat ik gedaan heb beschrijf ik dit in deze blogpost. Hierbij moet ik wel een belangrijke disclaimer plaatsen: Ubuntu 8.04. Als je zelf een andere distro gebruikt kan het zijn dat je andere commando's moet gebruiken.
Add Expires headers
Zonder expires-headers weet een browser niet hoe lang hij een object (webpagina, plaatje etc) moet cachen. Standaard laadt een browser aan het begin van een sessie alles, vervolgens worden plaatjes/js/css etc tijdens de duur van de sessie gecached. Dat betekent dat er over een sessie heen niets wordt gecached... Beetje zonde! En daarom gaan we de mod_expires installeren :D
Het grote voordeel: Snellere laadtijden
Het grote nadeel: Soms verouderde informatie

Installatie gaat makkelijk via het a2enmod commando:

code:
1
sudo a2enmod expires



Tot zo de installatie, nu nog het belangrijkste - de configuratie:
Bestand: /etc/apache2/apache2.conf
Locatie: In hoofd-scope

code:
1
2
3
4
5
6
7
8
9
10
11
ExpiresActive On
ExpiresDefault "now"
expiresbytype image/gif "access plus 7 days"
expiresbytype image/jpg "access plus 7 days"
expiresbytype image/png "access plus 7 days"
expiresbytype text/html "access plus 6 hours"
expiresbytype text/txt "access plus 6 hours"
expiresbytype text/js "access plus 7 days"
expiresbytype text/css "access plus 7 days"
expiresbytype text/javascript "access plus 7 days"
expiresbytype application/x-javascript "access plus 7 days"



Bovenstaande zorgt ervoor dat standaard bestanden niet worden gecached. Voor de belangrijkste bestandstypes zijn vervolgens uitzonderingen gemaakt, HTML en tekst mag elke 6 uur opnieuw worden opgevraagd door de browser, CSS, JS en plaatjes veranderen maar zelden dus die mogen na 7 dagen uit de cache worden gegooid.
Compress components with gzip
Gzip is een compressie-algoritme. Als je deze aan apache toevoegt wil dat zeggen dat apache niet de originele data maar de gecomprimeerde data naar de browser van een bezoeker stuurt. Deze browser pakt het dan automatisch uit en geeft het weer.
Het grote voordeel: Minder bandbreedte nodig
Het grote nadeel: Extra CPU belasting van server (en client)

Vroeger heette deze apache mod 'mod_gzip' maar sinds apache 2 heet het 'mod_deflate'. Het is te installeren met de volgende opdracht:


code:
1
sudo a2enmod deflate



Nu zit de module in apache, maar het is nog niet geconfigureerd. Omdat het geen zin heeft om plaatjes te gzippen (die zijn al gecomprimeerd) kiezen we voor de volgende configuratie:
Bestand: /etc/apache2/mods-enabled/deflate.conf
Locatie: In <ifmodule> scope

code:
1
2
3
4
5
6
7
8
9
10
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/x-javascript

# Voor logging (kan weg als je weet dat alles goed werkt:
# Begin logging stuk
DeflateFilterNote Input input_info
DeflateFilterNote Output output_info
DeflateFilterNote Ratio ratio_info
LogFormat '"%r" %{output_info}n/%{input_info}n (%{ratio_info}n%%)' deflate
CustomLog /var/log/apache2/deflate_log deflate
# Eind logging stuk



Nu is er standaard 1 probleem.... Apache weet niet welke bestanden als text/css of text/javascript of application/x-javascript worden verzonden. Daarvoor moeten we een kleine aanpassing doen:
Bestand: /etc/apache2/mods-enabled/mime.conf
Locatie: In hoofd-scope

code:
1
2
AddType text/css .css
Addtype application/x-javascript .js



Nu snapt apache dat alle .css bestanden van het mime-type text/css zijn, etc.

Dan rest nog 1 taak: Apache herstarten zodat de wijzigingen van kracht worden:

code:
1
sudo apache2ctl restart


Zo! Performance getweakt = mission complete! :D

Volgende: Laser + ogen 06-'09 Laser + ogen
Volgende: Usenet 4 dummies 05-'09 Usenet 4 dummies

Reacties


Door Tweakers user pat42, dinsdag 26 mei 2009 19:31

Heb je E-tags bewust nog aanstaan? Ik weet dat het op een lokale webapp niet veel uitmaakt (altijd dezelfde server), maar het is een beetje dubbel naast Expires en last modified header toch? Etags kunnen trouwens (o.a.) via je htaccess uitzetten met
code:
1
FileETag none


Door Tweakers user Cruz, dinsdag 26 mei 2009 19:35

Nee ik gebruik geen ETags; dit is een manier om bestanden een unieke identifier te geven die onafhankelijk is van de server waar hij op staat.

Dus stel dat je een CDN hebt waarbij je bijv 3 servers hebt voor het serveren van plaatjes:
img1.urdland.com
img2.urdland.com
img3.urdland.com

Je cached een plaatje dat vanuit de html pagina vanuit img1.urdland.com werd geladen. Bij een volgende pageview staat er in de html dat het plaatje op img2.urdland.com staat. Als je geen ETags gebruikt denkt de browser dat het een ander plaatje is en wordt hij van de img2 server gehaald ook al stond hij in de cache. Met ETags heeft het plaatje dezelfde 'tag' op alle servers en wordt hij dus uit de cache gehaald en niet van de server.


I stand corrected :) Ik had blijkbaar de uitleg van YSlow verkeerd begrepen. Zie crisps verhaal voor de juiste werking van ETags.

[Reactie gewijzigd op woensdag 27 mei 2009 14:52]


Door Tweakers user ACM, dinsdag 26 mei 2009 22:49

Vziw is Etags helemaal niet bruikbaar om net te doen of een bestand dat van verschillende urls komt, toch de versie is die in je browsercache staat. Wat het wel doet is een extra indicatie van de geldigheid van een file.

Het grootste nadeel van Etags is bij Apache in loadbalancing-pools op Unix-smaken, dat niet alleen de laatste tijd en filegrootte, maar ook de file's inode meegenomen worden in de Etag. En die inode is doorgaans per server verschillend en dus wordt ook de Etag vaak ten onrechte als verschillend gezien.

Afgezien daarvan is het inderdaad een redelijk overbodige toevoeging bovenop de expires header.

Overigens valt me op dat je erg korte expire-datums hebt. Voor met name javascript en stylesheets zijn er veel eenvoudigere manieren om af te dwingen dat een nieuwe versie geladen wordt - domweg door een GET-parameter toe te voegen (zoals bij ons de last-modified tijd), voor afbeeldingen is dat ook mogelijk, maar wat bewerkelijker.

Overigens is het aandeel van mod_deflate op de totale cpu-tijd van je server waarschijnlijk niet eens zo heel groot, dus om dat nou een 'groot nadeel' te noemen?

Door Tweakers user crisp, woensdag 27 mei 2009 01:29

Vziw is Etags helemaal niet bruikbaar om net te doen of een bestand dat van verschillende urls komt, toch de versie is die in je browsercache staat.
Klopt. In feite is er geen enkele manier om effectief clientside cacheing toe te passen op resources die van een ander url komen anders dan zorgen dat je voor dezelfde file dezelfde url gebruikt.
Wat het wel doet is een extra indicatie van de geldigheid van een file.
Het is meer een ander soort indicatie.
Afgezien daarvan is het inderdaad een redelijk overbodige toevoeging bovenop de expires header.
Als je op basis van last-modified effectief expires headers kan genereren en checken voegt het inderdaad niets toe en kan je ze beter weglaten (daar gaat de YSlow rule ook over; minder headers is ook minder overhead en Etag zorgt doorgaans voor meer roundtrips dan expires). Etag is nuttig wanneer je niet simpel op basis van een timestamp iets zinnigs kan zeggen over de validiteit van de clientside gecachede versie. Bij een dynamisch gegenereerde resource zou je bijvoorbeeld een checksum kunnen gebruiken als Etag.

Door Tweakers user Zjosh, woensdag 27 mei 2009 08:07

Wat merk je in de praktijk nou van deze verbeteringen? Zou wel leuk zijn een before en after benchmark ofzo :)

Door Tweakers user ZpAz, woensdag 27 mei 2009 09:48

Safari 4 heeft ook erg mooie 'performance' charts om te kijken wat het langste duurt om te laden, en daar kan je dus ook mooi zien waar je de meeste performance kunt winnen.

http://overig.indev.nl/uploads/safari_speed.png

[Reactie gewijzigd op woensdag 27 mei 2009 09:48]


Door Tweakers user Skinkie, vrijdag 19 juni 2009 00:42

Je kunt ook van webserver veranderen ;) http://www.cherokee-project.org/ ;)

Reageren is niet meer mogelijk