Ik heb recent mijn site opnieuw gemaakt. Hiervoor maakte ik altijd gebruik van een “Static site generator”, een script dat markdown bestanden omzetten naar HTML. Omdat ik nu WordPress gebruik is het nuttig dat ik kijk naar het optimaliseren van de performantie van mijn site.
Tag archieven: caching
Cachen met Apache en mod_cache
Een van de eenvoudigste manieren om de performantie van een drukke website te verbeteren is om caching toe te voegen. Er zijn verschillende manieren waarmee dit kan gebeuren: Je kan objecten cachen in code (met Memcached en Redis), of je kan de responses cachen met Varnish, Nginx of in dit geval met Apache’s mod_cache. Ik raad dit op zich niet aan in productie, maar omdat ik Apache gebruik als webserver leek het me een leuk experiment, zonder veel extra configuratie te moeten toevoegen.
Django Caching, i18n en Authenticatie
Django bied geweldige tools voor caching eenvoudig maken. Het heeft naar mijn mening wel 2 grote beperkingen:
- Het stuurt automatisch Cache-control headers, waardoor de client’s cache verhinderd dat de pagina goed herlaad als de taal gewijzigd word en er geen taal prefix in de url gebruikt word
- Het cached niet per gebruiker, waardoor als we niet opletten er mogelijks private informatie gelekt kan worden.
Beide van deze beperkingen waren oorspronkelijk een probleem bij het herschrijven van Skyz. Het eerste probleem kon deels verholpen worden door taalprefixes toe te voeren aan de url’s, de andere problemen kon ik oplossen op de volgende manieren.
Notes on caching
In een vorige post heb ik toegelicht hoe je caching kan toevoegen aan Django (en in de toekomst zal ik een post maken hoe je ook kan cachen op de webserver). Ik heb wat geƫxperimenteerd met caching en ik heb enkele dingen geleerd.
there are two things hard in computer science: cache invalidation and naming things
— Phil Karlton
Wat te cachen
Statische assets (CSS, Javascript etc) kunnen eigenlijk permanent gecached worden (of toch een langere periode, zoals een maand of een jaar), idealiter ook op de client. Alle andere inhoud moeten we mee opletten.
De homepagina op een drukbezochte site heeft vaak wel baat bij volledig gecached te worden (ook door downstream caches zoals de webserver of een CDN), maar eigenlijk enkel als de site geregeld bezoekerspieken krijgt. Pagina’s die niet veel bezoek krijgen worden beter niet gecached, omdat de kans groot is dat de gecachede versie nooit gebruikt zal worden.
Dure databasequeries worden vaak best gecached, net als externe API calls. Deze worden best gecached in bijvoorbeeld memcached voor zolang het acceptabel is dat deze gegevens “out of date” zijn, bijvoorbeeld 5 tot 10 minuten.
Cachen om te cachen is vaak de moeite niet, als een gecachede pagina nooit cache hits krijgt word er enkel geheugen verspild. In zo’n geval word er beter gekeken naar het optimaliseren van de site/code.
Cache toevoegen aan Django
Een cache toevoegen kan een enorme performantieboost zijn voor een website. Django maakt het eenvoudig om een cache toe te voegen, het laat out of the box 3 manieren om te cachen toe:
- Volledige site caching (elke pagina krijgt dezelfde behandeling)
- Per view caching (Er kan per view bepaald worden of er gecached moet worden, en voor hoelang)
- Low level caching (waar individuele objecten of databasequeries gecached kunnen worden.
Als ik bij een test applicatie per-view caching toevoeg als test, kan ik op een VM met 2 cores 600 requests/seconde verwerken in plaats van 200/seconde. In deze post zal ik toelichten hoe je per-view caching kan implementeren binnen Django
Caching met apache’s mod_cache
Caching is bij drukbezochte sites een must. Het verminderd de load op de webserver door de gegenereerde pagina’s op te slaan. Hierdoor word de database minder belast bij dynamische websites waardoor de webserver meer tijd heeft voor andere bezoekers.
Apache heeft een module, `mod_cache` die door middel van een paar opslagmechanismen (disk, shared memory, redis, memcached of zelf een DBM file) een snelle cache voorziet voor Apache. mod_cache is standaard als 1e laag in de processing stack, maar dit kan aangepast worden.
Eenvoudige configuratie
In de documentatie staat een voorbeeld van een eenvoudige configuratie. Als we deze
lichtjes aanpassen voor onze omgeving (in dit geval gaan we `/var/cache/httpd` gebruiken om de cache op te slaan, je moet deze map standaard zelf nog aanmaken).
<IfModule mod_cache.c> <IfModule mod_cache_disk.c> CacheRoot "/var/cache/httpd" CacheEnable disk "/" CacheDirLevels 2 CacheDirLength 2 CacheLock on CacheLockMaxAge 5 CacheIgnoreHeaders Vary DNT User-Agent Accept Accept-Encoding Accept-Language </IfModule> </IfModule>
Hierna moeten we zorgen dat mod_cache en mod_cach_disk zijn ingeladen met `a2enmod mod_cache mod_cache_disk`.
Vervolgens moet onze applicatie `Cache-control:` headers meegeven. Deze worden gebruikt om te vertellen hoe lang een pagina mag gecached worden. Afhankelijk van het soort pagina, en de updatefrequentie stel je deze in. Een blog waar vaak updates worden gepost is `300` seconden bijvoorbeeld een goed begin. Vaste pagina’s op die blog die zelden veranderen (zoals de ‘about’ pagina) kunnen dan weer een langere tijd krijgen, zoals `3600` seconden of zelfs `86400` seconden (1 dag).
Met apache komt standaard ook htcacheclean, een tool om de disk cache op te schonen. Deze tool kan je als daemon of als cronjob pereodiek uitvoeren om de groote van de cache map te beperken. Het onderstaande commando zal zorgen dat er maximaal 1GB aan data cachen, of 50000 inodes in gebruik nemen.
htcacheclean -p /var/cache/httpd -l1G -L50000 -n -t