Caching, de technischere uitleg.

Foto van Bernard

Geschreven door Bernard Zijlstra

Een lesje caching voor gevorderden

Caching van websites. We kunnen niet meer zonder, maar soms ook niet met. Althans, het is niet voor iedereen makkelijk te begrijpen wat, wanneer en op welk niveau er iets wordt gecached. Met ons artikel Caching, de niet-technische uitleg hebben we een toegankelijk artikel gepubliceerd om het concept uit te leggen. Met dit artikel gaan we wat meer de diepte in.

Waarom zien we na een nieuwe release met aanpassingen deze niet direct live terug? Ligt dat aan mijn internetbrowser, de hosting of aan de website zelf? En waarom zijn er zoveel verschillende soorten caching? En wat kunnen wij als bureau allemaal doen met caching?

Tijd voor een lesje caching voor gevorderden dus.

Wat is caching nu eigenlijk?

Caching bespaart rekenwerk door het resultaat van een berekening ergens, vaak tijdelijk, voor je op te slaan voor later gebruik en bespaart daarmee tijd. De beschikbare hosting capaciteit wordt hiermee efficiënter gebruikt. Als voorbeeld neem ik altijd de koffiekopjes in het keukenkastje. Als iemand mij nu vraagt hoeveel kopjes er in het kastje staan, dan moet ik eerst naar het kastje lopen en de kopjes tellen, dat kost tijd. Vraagt iemand anders mij een uur later nogmaals naar het aantal koffiekopjes, dan weet ik het antwoord niet meer en moet ik opnieuw gaan tellen. Dubbel werk, dat je simpelweg kunt voorkomen door het antwoord op te schrijven. Caching voorkomt terugkerend onnodig rekenwerk en daarmee zorgt het voor tijdswinst.

Wat doet caching dan precies met een website?

Een website voelt sneller aan door het inzetten van caching en vergroot de capaciteit om meer gelijktijdige bezoekers af te handelen. Caching zorgt voor meer efficiëntie in het genereren van HTML en het serveren van die HTML aan de website bezoekers. De server die de website uitserveert verbruikt minder rekenkracht per bezoeker en hoeft dus minder hard te werken. Hierdoor is het mogelijk om een groter aantal bezoekers gelijktijdig te bedienen zonder dat de website langzamer wordt of helemaal niet meer laadt. Een campagnepagina of een landingpage van een mailing worden vaak veel bekeken gedurende korte periodes en profiteren daarom enorm van caching.

Toch is het moeilijk om in detail uit te leggen wat caching nu precies is zonder heel technisch te worden. Er is namelijk niet één soort caching maar er zijn verschillende smaken die, afhankelijk van het project, samengevoegd kunnen worden. Caching passen we toe op een website in verschillende niveaus en op verschillende manieren. De aard van de website en het type bezoek zijn belangrijke indicatoren die de caching mix bepalen.

Welke niveaus van caching zijn er?

Naast de standaard caching mogelijkheden binnen WordPress zelf maken wij ook gebruik van de mogelijkheden van internetbrowsers en de uitgebreide caching mogelijkheden van de server die de WordPress website serveert.

Hiermee hebben we al drie verschillende niveaus waar we caching toepassen; Website, Server en Browser. Daarnaast zijn er op serverniveau ook weer meerdere niveaus te onderscheiden. Elk niveau kent weer verschillende opties, wat het samenstellen van een goede caching mix tot een complexe zaak maakt. Regelmatig hebben we te maken met meer corporate opdrachtgevers waar de ICT afdeling allerlei wensen, eisen en policies heeft die onze uitdaging verder vergroot.

Hoe pas je caching toe en met welke tooling?

Wat kan er in hoofdlijnen ingezet worden op de verschillende niveau’s?

1. Website

Om maar gelijk met ‘onze’ kant te beginnen. Onderstaande checklist passen wij toe op onze WordPress projecten en adviseren wij iedereen in te zetten:

De MySQL InnoDB buffer pool

Deze buffer slaat data en indexen op in het werkgeheugen van de server en bespaart daarmee veel tijd door het voorkomen van interactie met de opslag van een server en MySQL. De MySQL InnoDB buffer is backend gerelateerd en maakt van je database een in-memory database. Zorg dat de buffer groot genoeg is voor je database. Denk hierbij aan informatie zoals;

  • Welke berichten en pagina’s op de website bestaan
  • Inhoud van berichten en pagina’s
  • De auteurs en gebruikers die er zijn
  • Actieve plugins

De MySQL Query cache

Wij hebben de Query cache meestal niet meer aanstaan. Hij is alleen nuttig wanneer de informatie op de website weinig of niet verandert. Deze cache houdt informatie vast van select statements, maar moet worden ververst bij elke update of insert op de tabel die bij deze select gebruikt wordt. Vanaf MySQL versie 5.7 is de Query cache deprecated en zal in de volgende major release verwijderd worden.

PHP OPcache

Wij gebruiken de PHP OPcache bij elke website om de PHP code die de server uitvoert op te slaan in het het gedeelde werkgeheugen in een tussenvorm die bytecode heet. Best vaak zijn problemen die ontstaan na een aanpassing van de PHP code te herleiden naar deze cache. De server voert dan nog de opgeslagen bytecode uit, in plaats van de aangepaste PHP code. Daarom starten we bij de verwerking van aanpassingen op de productieserver automatisch het PHP proces, om te zorgen dat deze cache leeg wordt gemaakt.

WP Object Cache

Vaak laat je op een pagina meerdere keren dezelfde informatie zien, zoals de naam van een auteur. Het is inefficiënt hiervoor meerdere keren de database te raadplegen, omdat we vooraf al weten dat we dezelfde informatie terugkrijgen.

WordPress zorgt er automatisch voor dat hetzelfde object per pagina-refresh maar 1 keer geladen wordt, door middel van de Object Cache. Normaal gesproken doet WordPress dit voor ieder verzoek opnieuw, maar bij klanten met buitengewoon veel verkeer willen wij hier nog wel eens een aparte oplossing voor gebruiken, zoals Redis. Redis zorgt ervoor dat items uit de Object Cache langer bewaard kunnen worden en gedeeld kunnen worden. Door WordPress wordt standaard al veel informatie over gebruikers en berichten in de cache opgeslagen.

Voor onze maatwerk thema’s gebruiken we de WordPress cache nog wat efficiënter. Daarbij gebruiken we de wp_cache_get() en wp_cache_set() functies. Op die manier slaan we bijvoorbeeld de goedkoopste verzendmethode op voor een bestelling in je webshop. Dan hoeft de winkel dat niet elke keer opnieuw uit te rekenen.

Transients cache

Voor de snelheid van je website ben je niet graag afhankelijk van andere websites. Het laden van informatie uit een externe bron voegt zo 10 tot 30% toe aan de wachttijd voor een bezoeker. Een eeuwigheid voor computers. Om te voorkomen dat de door ons ontwikkelde website trager wordt vanwege een externe bron slaan wij deze ‘dure’ handelingen standaard op in transients. Deze worden in tegenstelling tot de Object Cache wel tussen meerdere gebruikers en pagina’s gedeeld. Afhankelijk van de bron slaan wij deze resultaten voor een aantal seconden tot uren op. Standaard worden transients opgeslagen in de options tabel, queries zijn duur, door het inzetten van Redis worden transients in werkgeheugen opgeslagen en niet meer in de database.

Rewrite rules

De rewrite rules van WordPress bepalen welke URL welke pagina laat zien. Wanneer nieuwe post-types worden toegevoegd of een API-endpoint wordt ontwikkeld, moet de lijst van verwijzingen ververst worden zodat WordPress de koppeling correct kan maken. Dit is eenvoudig te herkennen, wanneer de link voor een preview wel goed werkt, maar dezelfde pagina als ‘mooie’ url een 404 geeft. We kunnen niet automatisch herkennen of de wijzigingen in de code een reset van de rewrite rules nodig heeft. Daarom verversen we deze lijst standaard bij elke deploy.

Standaard caching door WordPress

Soms zitten er in WordPress standaard caching mechanismen. Een voorbeeld hiervan is de fetch_feed functie, die wordt gebruikt om XML bestanden zoals sitemaps in te lezen. Deze functie bewaard het resultaat zonder specifieke instructies standaard 12 uur.

Twig Templates

Met behulp van de door Level Level ontwikkelde Clarkson-Core open source oplossing, maken we het mogelijk om site elementen te hergebruiken. Dit gebeurt op de achtergrond met Twig templates. Het bij elkaar zoeken van de juiste templates kost rekenkracht, en ook hier kunnen we weer winst halen door het resultaat tussentijds op te slaan. Deze tussen-producten worden als php bestanden in een tijdelijke map op de server opgeslagen. Bij een deploy legen wij deze map, zodat de tussen-bestanden opnieuw gegenereerd worden.

Plugins

Soms bepalen plugins zelf wat voor caching regels ze aanhouden. En ze zijn lang niet altijd ontworpen om efficiënt te werken met grote hoeveelheden bezoekers. Daarom bekijken we bij Level Level altijd kritisch of een plugin niet alleen aan de functionele eisen voldoet, maar ook op het gebied van code kan bieden wat er nodig is bij een klant.

2. Hosting

Caching op de infrastructuur, is besparen op de beschikbare rekenkracht van de server. Als wij ook de WordPress hosting mogen verzorgen voor een website, stemmen we voor elk project vooraf de caching-mix af op de requirements van het project. En vullen wij de al eerder genoemde caching mogelijkheden waar nodig verder uit.

De server cache’s zorgen voor betere gebruikerservaring van bezoekers en lagere kosten.

MySQL

Naast de InnoDB buffer pool heeft MySQL nog honderden andere configuratie mogelijkheden. Wij beginnen altijd met een eigen standaard configuratie die we gedurende de afgelopen jaren zelf hebben samengesteld op basis van inzicht en ervaring. Daarnaast voeren we met regelmaat analyses uit en houden we de slow querylog in de gaten, om de configuratie bij te sturen en/of queries in de website te optimaliseren.

Redis

Redis, al eerder genoemd, bewaart WordPress objecten zoals posts of auteurs en transients tussen verschillende requests, zodat we minder informatie aan de database te hoeven op te vragen. Naast WordPress koppelen we ook andere onderdelen aan Redis zodat we zoveel mogelijk gebruik maken van de snelheid van het werkgeheugen van de server.

NGINX

Wij zijn groot liefhebber van de NGINX proxy- en webserver. NGINX is snel en gaat gemakkelijk om met grote hoeveelheden bezoekers. Daarnaast implementeert zijn snel nieuwe technieken, zoals SPDY de voorganger van HTTP2.0 of de nieuwe 1.3 versie van TLS. Daarnaast beschikt NGINX standaard over zeer goede pagecaching zodat volledige HTML pagina’s uit de cache gehaald worden en PHP veel minder werk hoeft te verzetten.

Varnish

Varnish slaat (delen van) de resulterende HTML pagina’s op in het werkgeheugen van de server (pagecache), zodat PHP helemaal niet meer aangesproken hoeft te worden. Deze functionaliteit zit ook in NGINX maar sommige projecten vragen om meer logica in de cache configuratie of hebben een redundante oplossing nodig achter een loadbalancer. Dan is Varnish onze keuze.

3. De ‘klant’ kant

Ja. We kunnen niet alles controleren. Want we hebben ook nog caching aan de kant van je website bezoeker. Caching door besturingssysteem en de webbrowser.

DNS requests

Het domein van een website en de plek waar de server staat worden aan elkaar gekoppeld door middel van een DNS verzoek. Wanneer een nieuwe website online komt of naar een andere server wordt verhuist kan het een paar uur duren voordat iedereen de juiste verwijzing krijgt omdat ook de DNS tijdelijk lokaal opgeslagen wordt. Een paar dagen voordat we een domein naar een nieuwe website laten verwijzen, verlagen wij de cachetijd in het DNS systeem.

Browsercache

Afbeeldingen, HTML, fonts, CSS (voor de styling van een website) en JavaScript bestanden (voor de interactiviteit) worden vaak bij de bezoeker lokaal opgeslagen, zodat de browser deze niet bij elke nieuwe pagina hoeft te downloaden. Wij gebruiken een uitgebreide configuratie in NGINX die de cachetijd van de verschillende onderdelen meegeeft aan een webbrowser d.m.v. HTTP headers.

Als bezoekers willen forceren dat ze een nieuwe download starten, moeten ze de browser cache legen. Wanneer wij een nieuwe versie van de website publiceren hoeft dit echter niet. We geven namelijk aan elke wijziging een nieuw versienummer mee. Op die ziet de browser van de gebruiker dat er een nieuwere versie beschikbaar is om te downloaden.

Webpagina’s slaan we over het algemeen liever niet op in de browsercache. Het is dan moeilijker om de bezoeker op hoogte te stellen als er een bijgewerkte versie beschikbaar is. Daarnaast is er dan minder informatie beschikbaar voor analyse op de webserver.

Proxycache

Binnen grote organisaties of remote werkplekken wordt vaak inkomende informatie van een website opgeslagen in een zogenaamde ‘forward proxy cache’. Dit gebeurt om bandbreedte te besparen voor veelbezochte websites of vanuit security overwegingen. In een ideale situatie leeft z’n proxy de regels die aangegeven worden door de website na, maar dit is lang niet altijd het geval en worden pagina’s langer opgeslagen dan zou moeten.

Localstorage

Met behulp van moderne technieken zoals PWA is het ook mogelijk om websites (gedeeltelijk) offline beschikbaar te maken. Hierbij is het soms moeilijk te controleren wat de meeste recente up-to-date versie is voor een gebruiker.

Waarom kunnen er problemen ontstaan bij caching?

Kan die complexiteit en de verschillende niveaus van caching en de verschillende betrokken partijen bij caching voor problemen zorgen?

Om beter te begrijpen waarom caching soms voor problemen kan zorgen, zijn de koffiekopjes in het keukenkastje weer een goed voorbeeld. Want het onthouden, hoeveel kopjes er zijn, heeft dus ook risico’s. Want wat gebeurt er als er in de tussentijd een kopje kapot valt? Wie controleert dat? En hoe zorgen we dat deze informatie overal beschikbaar is en op verschillende locaties? Want als het aantal koffiekopjes verandert, dan moet de opgeslagen informatie, in dit geval het aantal kopjes, aangepast worden.

En waarom niet gewoon een caching plugin?

Een groot deel van de kracht van WordPress zit ‘m in het plugin ecosysteem. En er is natuurlijk ook een breed scala aan WordPress cache plugins beschikbaar. De bekendste zijn WP Super Cache en W3 Total Cache.

Voor onze maatwerk websites hebben we graag iets meer controle. Op die manier kunnen we de verschillende caching lagen specifiek afstemmen op de benodigdheden van de website en zo de maximale performance er uit persen. Dan blijft je website dus ook tijdens grootschalige TV campagnes of met miljoenen bezoekers snel en bereikbaar.

Conclusie

Caching kan dus veel moois betekenen voor websites. Maar caching is geen wondermiddel. Snelheid van een website begint altijd met een efficiënte manier van je code opbouwen. Je website moet in de basis simpelweg al snel zijn zonder enige vorm van caching. Caching mag niet misbruikt worden om een slecht gebouwde website sneller te maken. We zetten caching dus in als optimalisatie en niet als noodzaak.

Caching zorgt ervoor dat:

  • Een website meer gelijktijdige bezoekers kan afhandelen zonder traag te worden. Je hoeft niet meteen flink te investeren in duurdere hosting van je website als deze populair wordt.
  • Een dynamische website met veel inhoudelijke content toch snel kan laden in de webbrowser van je bezoeker.
  • Data die uitgewisseld wordt tussen je website en een webbrowser zo optimaal mogelijk is, minder te verzenden MB’s is goed voor de portemonnee van de website eigenaar en voor de mobiele bezoeker.
  • Het integreren van externe informatiebronnen in je website niet automatisch betekent dat deze website trager wordt.

Vertel ons meer over je plannen en ambities!

We zijn klaar om jullie online uitdaging op te pakken.