Bij het opzetten en onderhouden van een online platform komt veel kijken. Ook veel technische zaken. Hoewel het niet het meest sexy deel is van je platform, heeft het wel degelijk veel invloed op de performance van de site en de ervaring van gebruikers. Op een langzame site zit immers niemand te wachten. In deze blog ga ik in op enkele maatregelen die we recent op Marketingfacts hebben getroffen om de lange laadtijden op te lossen.
Het probleem
Na de lancering van de nieuwe site hebben we enkele dagen, samen met Mangrove en Exonet, gemonitord hoe de site het hield. Zonder redundante oplossing is dat toch spannend, maar het ging boven verwachting. Wel heeft Mangrove tijdelijk volledige pagina's moeten cachen, waarmee wel de werking van enkele dynamische onderdelen werden gedwarsboomd. Bijvoorbeeld de kliktellers, die bij elke view moet worden geüpdatet. Bij de optimalisatie van deze sociale knoppen komt heel wat kijken, zie deze eerdere blog.
Na enkele weken kregen we steeds vaker problemen met de performance. Na wat eenvoudige tweaks ging dat voor korte tijd even goed, maar het probleem bleef terugkomen. Uiteindelijk bleek dat we massaal gespamt werden via een set standaard formulieren van Expression Engine. De site kreeg daarmee elke 10 seconden een nieuwe aanmelding te verduren. In combinatie met het normale bezoek zorgde dit ervoor dat de laadtijden van de site enorm terugliepen.
Om voor awesome laadtijden te zorgen zijn we bij elkaar gaan zitten en hebben we een stappenplan opgezet om tot structurele verbetering te komen. In deze blog wil ik je meenemen in de maatregelen die we samen met Robert Leefmans, Nick Rockx en Amer Grgic van Mangrove en Jesper Weiland van Exonet hebben getroffen.
Database tabel type
Allereerst heeft Mangrove de het tabeltype van de database aangepast. Globaal gesproken zijn er twee soorten: MyISAM en InnoDB. MyISAM is voor MySQL de standaard wijze waarop informatie wordt opgeslagen in de database, en daarom maakt het gros van de sites gebruik van MyISAM. Ook Expression Engine, het CMS waarmee Marketingfacts is gebouwd, maakt gebruik van de standaard storage engine (zoals het officieel heet). In de meeste gevallen MyISAM dus.
Tussen beide type database engines zitten veel kleine technische verschillen. Zo is InnoDB makkelijker te backuppen en beschikte InnoDB tot voorkort niet over full-text search. Details, zo lijkt het, maar hebben mogelijk grote impact. Het belangrijkste verschil is dat MyISAM op tabelniveau versleuteld, en InnoDB op rijniveau. Wat betekent dit nu concreet? Bij het laden van de homepage worden er flink wat verzoeken aan de database gedaan. Artikelen, reacties, maar ook voor elk artikel wordt opgehaald hoeveel kliks en social shares er zijn. Bij elk van zo'n request wordt er een bewerking op 1 (of meerdere) tabellen. Een tabel is in deze zin overigens niet anders dan 'gewone' gegevenstabellen; bv. een klanttabel, ledentabel, reactietabel, etc.
Als zo'n verzoek wordt gedaan in het geval van MyISAM doet het systeem de tabel tijdelijk op slot, zodat er geen conflict kan ontstaan met andere processen. Dit zou bijvoorbeeld voor problemen kunnen zorgen wanneer er, vrijwel tegelijkertijd, bestellingen worden gedaan van eenzelfde account. Als er niet genoeg tegoed op de bijbehorende rekening staat bestaat het risico dat beide transacties worden voltooid. De locking zorgt ervoor dat eerst transactie nummer 1 wordt voltooid, voordat transactie nummer 2 in werking wordt gezet.
Wel zo veilig dus. Maar het kan er voor zorgen dat de snelheid bij druk bezoek behoorlijk wordt verlaagd. Bij InnoDB tabellen worden geen gehele tabellen gelockt (zoals links afgebeeld), maar gebeurt dat per record/row (afbeelding rechts). Dat zorgt ervoor dat wanneer 'John' uit de database wordt opgehaald, tegelijkertijd 'Bob' of 'Steve' kan worden opgehaald zonder dat deze hoeft te wachten tot het ophalen van 'John' voltooid is. Een klein verschil, maar met een site met veel bezoekers, en daarmee veel requests, kan het een enorme snelheidswinst opleveren. Met name wanneer er wat zwaardere processen tussen zitten die lang beslag kunnen doen op een tabel, en zo voor een file kunnen zorgen. Met het risico dat de site er uit klapt tot de file is opgelost.
Caching
Mangrove heeft met diverse manieren van caching geëxperimenteerd. Exonet was fan van MemCache, en dat werd als eerste getest. De integratie met Expression Engine verliep echter niet soepel als we zouden willen. Er traden nogal wat 'vreemde' bij-effecten. Het ging mis bij de dynamische onderdelen, o.a. sessiedata werd meegecached en kwam bij andere bezoekers terecht.
De oplossing waar Mangrove voor heeft gekozen is het cachen van zogeheten partials. Het is vergelijkbaar de caching in Mangrove's eigen pH8.CMS, en betekent in feite niets anders dat dan gepaalde onderdelen of objecten wél, en bepaalde niét worden gecached. Hiervoor moest de site opzet, die Expresion Engine eigen gericht is op het snel parsen, iets aangepast worden. Een aantal voorgeprogrammeerde blokken code die, door parsing, eenvoudiger worden geladen zijn vervangen met de meer standaard includes waarbij je meer cachemogelijkheden hebt. Met deze aanpassing blijft dynamische content bij elk bezoek vers ingeladen, maar worden meer statische elementen langer gecached.
Resultaat
De aanpasingen zorgde ervoor dat de responsetijden flink zijn teruggelopen, zie ook onderstaande tabel:
Dankzij de aanpassingen is de performance nu zeker acceptabel. Mocht de load toch hoog oplopen, dan heeft Mangrove vervolgstappen klaarliggen. Nick Rockx: "Wat we bij groeiend bezoek nog kunnen gaan inzetten is het cachen en uitserveren van statische content vanaf speciaal daarvoor ingerichte servers. Daarnaast zouden we de hosting nog kunnen opschalen naar een redundante opstelling met meerdere database- en webservers."
Afbeelding: Esparta (cc)
Afbeelding 2: Joisey Showaa (cc)